AdSense approved the ads.txt — the hub pages had nothing for reviewers to evaluate

The AdSense notification arrived on 10 July at 17:42 BST. Three words: “Needs attention — Low value content.” Directly below: ads.txt status, Authorised.

That pairing defines the problem precisely. Authorised means the seller-ID chain from the ads.txt file to the AdSense publisher account was verified and intact. The rejection didn’t come from that check. It came from what Google’s reviewer found when they visited the site.

Ads.txt is not the bar

The ads.txt file declares which ad networks are authorised to sell inventory on a domain. Google’s crawler verifies it during the initial review: does the seller ID in the file match the AdSense publisher ID? If not, the review ends there. If yes, the authorisation check passes and Google evaluates the content.

On 10 July, it passed. Authorised from day one. The rejection was entirely downstream of that.

Most AdSense troubleshooting guides treat ads.txt as the primary variable because it’s the most legible failure mode. Present or absent. Matching or not. It has a clear fix. Content quality doesn’t have a clear fix, which is why it tends to get addressed last, or not addressed at all.

Two sequential gates. Ads.txt is the entry requirement; inventory-value evidence is the interview. Conflating them wastes a week.

What Google’s reviewer actually visits

After mapping the failure routes, the nature of the problem became clear.

/resources/blog and /resources/guides are the content-hub pages for the site. They’re the first routes a reviewer checks on a publication-type property: they tell the reviewer whether there’s a real editorial operation behind the domain or just a thin shell of pages.

Before the fix, a reviewer visiting either route would have found a rendered layout with no article listings. The route existed. The page structure loaded. The content index was empty.

That’s not thin content in the sense of shallow articles. It’s a page that presents nothing to evaluate. Google’s inventory-value policy found a literal match: /resources/* routes presenting skeleton pages isn’t low value in degree, it’s low value in kind. There’s no inventory there.

What had already been addressed before the rejection

The rejection arrived after several rounds of preparation, not before.

The AdSense readiness audit against Google’s reviewer checklist scored 7 of 8 green before the review request went in. The one failing signal: “diverse and engaging content in a variety of formats (articles, images and videos).” At that point, 0 of 38 pages had images. A measurable gap.

That closed on 2 July. An ArticleFigure component and 6 verified SVG diagrams shipped across the pillar estate. The media-diversity signal moved from red to green. The checklist hit 8 of 8.

Before that, I expanded five thin surfaces (four calculator landing pages and a gilts explainer) via an ultracode workflow. Those had been flagged in an earlier readiness assessment. They were resolved before the review opened.

At submission time: 78.6% indexation, 8 pillar publishes in 4 weekdays, no policy strikes, Auto Ads enabled. Every self-assessed signal green.

The hub routes weren’t on the checklist. That’s the gap the rejection exposed.

The telemetry layer

The B-078 AdSense telemetry skill shipped on 2 July. It queries approval status, earnings, and payments via the AdSense Management API v2 — read-only, Keychain-secured credentials. First live read: account READY, site GETTING_READY (review in progress), no policy strikes.

The OAuth setup had friction: the first cli.py auth attempt failed silently on a blank or mistyped paste at the client-id prompt. Second attempt clean, after fetching the correct client credentials from Keychain. The skill is now stable.

GETTING_READY is the expected status during review, not a warning. The rejection on 10 July moved that status. The telemetry reads the current state via API rather than manual UI polling, which matters when a resubmission is in progress and you want to know when the verdict changes without opening a browser.

Remediation #1

The label is deliberate. #1 means the first of what may be several passes before the site moves from rejected to approved.

The fix was specific: real hub listings for /resources/blog and /resources/guides. Not more content, not additional pillar pages, not further keyword expansion. The articles already existed; the hub pages weren’t indexing and presenting them.

That distinction matters. The preceding weeks had focused on content creation: pillar articles, thin-surface expansion, image diversity. Those were content problems. The hub-listing problem was a presentation problem. The inventory existed; the hub routes weren’t making it visible to a reviewer, or to a user.

A reviewer visiting /resources/blog after the fix encounters a populated index of published articles. Before: a rendered skeleton. After: a navigable list with real content. The inventory-value signal shifts category, not degree.

Google’s inventory-value policy is asking a direct question: is there a real editorial operation here, or just infrastructure with pages on it? A skeleton hub page answers that question in the wrong direction regardless of how much content lives elsewhere on the site.

What this clarifies

The 10 July rejection was a correct call. The ads.txt authorisation was never the issue. The hub routes had no listings, and the reviewer found nothing to evaluate on the most navigable paths on the site.

Ads.txt authorisation is table stakes. It gets you into the review. What happens in the review depends on whether the routes Google’s reviewer visits have real inventory to evaluate. On 10 July, two of the most important ones didn’t.

Remediation #1 addresses the most immediate gap. Whether it moves the site to approved is what the resubmission will determine. The telemetry is running.

All writing