Content Quality Audit
astromatrix.org · content quality

Where the content itself is the problem

GA4 property 394497034 · 90-day window
pulled 2026-09-10 · pagePathPlusQueryString

Engagement time on /horoscopes/* pages, split three ways — category, planet/point, and individual page — to separate a template-wide problem from a genuine content-quality defect. 259 individual pages run at under half their own category+planet cohort's median engagement time despite comparable traffic: same aspect, same house, same sign, same generation pipeline — just a weak write-up.

13,083
horoscope pages scored (90d)
17 / 25
categories / planets with reliable volume
259
pages flagged — content, not category
6,356
sessions/90d landing on a flagged page
The Lilith case, checked directly: the two pages you named — venus-opposition-saturn (planet-aspects) and lilith-in-2nd-house (planets-in-houses) — confirm at 135.5s vs 56.9s engagement, 40% vs 74% bounce, on 173 vs 186 sessions in this 90-day window (your original spot-check used a shorter window, hence the different absolute seconds, but the gap direction and rough magnitude hold). And it's not a Lilith problem: aggregated across every Lilith page in the core categories, Lilith averages 126.9s — almost exactly the sitewide category norm. lilith-in-2nd-house and lilith-opposition-venus (the #1 and #2 worst individual flags below) are two bad pages inside an otherwise-healthy cohort, not a Lilith-wide issue.

1 · Category level

session-weighted avg. engagement time, 90d, real (non-bot) URLs only
The macro layer. Composite/progressed/draconic families run structurally shorter engagement — expected, they're the smaller/newer categories — while the four flagship categories (planet-aspects, transit-aspects, synastry-aspects, planets-in-houses) cluster tightly around 114–132s. That tight clustering is exactly why the within-category spread found in section 3 is notable: the template isn't the variable.

2 · Planet / point level

session-weighted avg. across all core categories, min 50 sessions
The 10 major planets plus Sun/Moon sit in a narrow 120–140s band on blended traffic. The minor/derived points — True Node, Eris, IC, Ceres, Juno, Midheaven, Pallas — run 20–60% below that blended band. Traced this further and it is not a content problem — see the correction directly below the chart.
Correction after channel breakdown: the minor-point gap fully closes once bot/scripted "Direct" traffic is separated out. Every minor point runs 55–80% Direct-channel share vs. 31–43% for the majors — and Direct engagement is near-zero (single-digit seconds, 80%+ bounce, the same space/plus-encoded-URL bot signature the original SEO audit already diagnosed). Real Organic Search visitors show no gap at all: Eris 196s, Ceres 194s, Pallas 205s, Juno 183s, Midheaven 173s — sitting right alongside Venus (196s), Mars (179s), Sun (185s). A URL-guessing script enumerates every combinatorial page at roughly the same rate, but genuine search demand for "Ceres in the 9th house" is inherently far smaller than for "Venus in the 9th house" — so the identical bot volume is a much larger share of a minor point's total traffic, dragging its blended average down even though the writing performs identically for real readers. No content-depth issue here, no rewrite needed — this is the Cloudflare/bot-throttling lever from the original audit, not a copy problem. (True Node and IC have too little organic volume, 81 and 304 sessions/90d, to read much into their own numbers either way.)
Planet / pointTotal sessionsDirect shareOrganic sessionsOrganic-only engaged

3 · Individual pages — content-quality flags, reconciled

original 259 flags, re-verified against organic-only traffic and a 365-day window
The first pass (ratio < 0.50 vs. cohort median, 90d blended traffic) flagged 259 pages. Two things could make that number wrong in either direction: a low-session page's average is just a couple of long/short visits away from being noise, and blended traffic includes the same Direct/bot contamination that turned out to fully explain the "minor points" pattern in section 2 — it could just as easily be quietly skewing individual pages. So every flagged page was re-checked two ways: organic-search-only sessions/duration (removes the bot channel entirely) where there's enough organic volume to trust, and a 365-day window for pages too thin to read at 90d. Verdict per page:
177
confirmed — still weak on clean traffic
35
cleared — was bot dilution, not content
47
insufficient data even at 365d/organic
259
total original flags reviewed
Page Category Planet Verdict Sess. 90d Engaged 90d Organic sess. Organic engaged Organic ratio Sess. 365d

4 · Template / Core Web Vitals check

Asked whether page-load or ad-weight differs by template (houses vs. aspects vs. signs), since that would drag down engagement independent of the writing — would explain cases where the copy reads fine (e.g. Saturn Conjunct Natal Sun, Mars Conjunct Mars) but still underperforms.
Partial answer, flagged honestly as incomplete: read the actual render path (app/horoscopes/[...slug]/page.tsx) directly — every category renders through the exact same component tree (same article body, same image, same Sidebar), with the only category-conditional difference being a single lightweight text CTA link (e.g. "Open Synastry Chart" vs. "Open Transit Chart"). No ads, no per-category widgets, no heavier embeds anywhere in the template. Structurally there is no reason one category should load slower or carry more weight than another. That said, this is a code-level answer, not a field-data one: there's no on-site Web Vitals instrumentation (confirmed by repo-wide grep — no web-vitals, LCP/INP/CLS reporting anywhere), and both the public PageSpeed Insights API and Chrome UX Report API came back inaccessible from this environment (PSI: daily quota exhausted on the linked GCP project; CrUX: needs an API key that isn't provisioned here). If real field CWV data is wanted, it needs either a CrUX API key provisioned, or `web-vitals` wired into the existing GA4 event stream (report as a custom event, then it's queryable the same way as everything else in this audit) — neither exists yet.

5 · Content bugs, verified on the live site

all 177 confirmed pages scanned on astromatrix.org directly (not the backend API alone)
Fetched the live rendered HTML for all 177 pages (the backend content API turned out to serve flaky/duplicate records inconsistently — see below) and scanned for leaked AI meta-commentary, empty/placeholder content, and garbled/non-dictionary text.
One confirmed, unambiguous content bug — and it's the #1 highest-impact page on the whole list. /horoscopes/planet-aspects/lilith-opposition-venus (145 sessions/90d, the single largest impact score in the dataset) currently renders genuinely corrupted text on the live site: "Lilith, the heavenly bodhis carpendulumlling rebellious spirit, falls opposite Venus…" — "carpendulumlling," "efflicomenormatus," "dimorchamberfreent," "consistenuerooperares" are not words; this is broken/garbled generation output that shipped to production. Worth noting: calling the backend content API directly for this same page returned a different broken variant (visible leaked model reasoning: "I'm looking at the source material here, and it has deteriorated into incoherence by the third paragraph…I'll rebuild") — the API appears to hold multiple duplicate records under the same key (matches a pattern already noted in app/lib/api.ts's own code comments) and serves them inconsistently. Whatever is live on the site right now is genuinely broken and should be the first thing fixed, independent of anything else in this audit.
That bug is isolated, not systemic. Only that one of 177 came back broken. One page that looked like a second bug via the direct API call (juno-in-aquarius, "currently unavailable") turned out to be API flakiness only — the live site already has retry logic for exactly this case and renders real, well-written content. Verify against the live page, not just the backend API, before calling something broken.

6 · Systematic pattern analysis

all 177 confirmed pages paired against their best same-cohort sibling (same category × planet, same template) — 354 pages fetched and scored, not a handful of spot checks
Every confirmed weak page was matched to the single strongest-performing page in its own (category × planet) cohort — same template, same generation pipeline, real content. Both sides of all 177 pairs were fetched from the live site and scored on 8 measurable text features, then compared as paired means and correlated against engagement duration.
FeatureWeak meanStrong meanDiffr vs. duration
Every feature is a wash. Word count, sentence count, sentence length, second-person ("you") density, question count, vocabulary diversity, and Flesch reading ease all differ by low single-digit percentages between weak and strong siblings, and none correlates with duration within the weak set itself (all |r| < 0.17, i.e. no relationship). None of the standard writing-quality proxies explain the gap. This is the same conclusion the 6-page manual read reached earlier, now checked across the full 177 pairs instead of a sample.

Self-aspects (a body vs. itself)

2.2×
over-represented in the weak list

Pages like mercury-conjunct-natal-mercury or mars-conjunct-mars (synastry) — a planet relating to itself rather than to a different point. Base rate across all 4,213 scored pages: 3.54%. Share of the 177 confirmed weak: 7.91% (14 pages). Real, but modest — not the dominant driver.

Minor aspect types (inconjunct / sesquiquadrate)

1.6×
over-represented in the weak list

Base rate: 6.01% of all aspect pages. Share of the 177 confirmed weak: 9.60% (17 pages). But not because these aspect types are inherently weaker — sitewide, inconjunct/sesquiquadrate run 65–86% Direct/bot share (the same dilution mechanism as section 2's minor planets), and once isolated to organic-only traffic they engage as well or better than the major aspects (193.8s / 210.5s organic vs. 185.5–233.0s for conjunct/square/trine/sextile/opposition). These 17 specific pages were independently re-verified on their own organic-only sessions in the reconciliation pass and still read weak individually — so they stay on the list — but "inconjunct pages are worse" as a category claim is false.

Category representation: proportional, not skewed

Category% of all pages% of 177 weakOver-rep.
Every major category sits within ~1.2× of its own population share — confirms section 1's category-level finding: no category is disproportionately generating weak pages. (Composite/progressed rows are noisy small-n and not meaningful on their own.)
Where this leaves it: across 8 measured text features on 177 real pairs, nothing in the prose itself explains the gap. Two structural patterns are real but modest (self-aspects 2.2×, minor aspect types 1.6× — together accounting for well under a third of the list, with overlap). The one unambiguous defect (section 5) is a single corrupted page. For the remaining ~160 pages that don't fit either pattern, the driver almost certainly sits outside the content itself — most likely reader search-intent match (what someone actually searched to land here vs. what the page delivers), which this audit hasn't checked yet since it requires Search Console query-level data, not GA4 engagement data.