The playbook
SEO mistakes we made, and the rule each one produced
These are 33 SEO mistakes we made on our own sites in September and October 2026, each with what happened, when, and the rule it produced. They cover choosing searches and titles, programmatic pages, reading positions, content agents, images and operations. Heddle's checks and agents are built from these rules, and each one keeps its evidence so nobody argues it away later.
Targeting
Articles were aimed at phrases nobody types (September 2026)
Two of the first three long articles were researched for days and measured at 10 and 210 searches a month.
The rule. Measure demand before choosing any topic or title.
The best gain was a retitle, not a new page (September 2026)
A good guide chapter sat at #53 for a 2,400-a-month term because its title was written for a contents list.
The rule. Check what already ranks on pages two to five before writing anything new.
Titles written from the company's side lost (October 2026)
Event pages went through three titles before leading with the event's own name, which is what the ranking pages used.
The rule. Read the live results page before shipping a title and lead with the searcher's exact phrase.
Vendors rename products faster than the internet updates (September 2026)
"Gold Partner" had been retired for four years; two product names had changed in the vendor's own docs.
The rule. Before a product name goes in a title, read the first sentence of the vendor's current documentation page for it.
Four phrasings read the same 27,100 (October 2026)
A product site's plan ranked "seo agent" near the top at 27,100 a month; "seo agency", "seo agencies" and "seo for agencies" read exactly the same volume at the same $39.88. Google Ads had grouped them as close variants, and most of the number belonged to agencies.
The rule. Identical (volume, cost per click) across phrasings that mean different things is one bucket; the research agent probes each term's neighbours in the same keyword call, strategy plans the bucket at its share and marks it unverified until the results page is read.
"aeo" was a stock ticker (October 2026)
The same reading measured "aeo" at 27,100 for $1.84 a click, against $25.49 for "answer engine optimization", and page one led with a retailer's share price.
The rule. A short acronym with a cheap click and an off-subject page-one leader is another meaning; plan it as unknown and target the expanded phrase.
A retired name kept its searches (September 2026)
A vendor's renamed AI product still drew 1,900 searches a month under the old name.
The rule. Write the page that resolves the old name to the new one; never adopt the old name, and list it in forbidden claims.
Programmatic pages
Two city pages shared 67% of their sentences (September 2026)
The rule. Every family has required per-row fields, and uniqueness is measured on built HTML against a ceiling (80% by the eight-word-sentence measure).
Thirteen of twenty-five pages in one family were never fetched (September 2026)
Each page linked to the first nine siblings of a fixed list, so the same nine got all the links.
The rule. Link every sibling or rotate; link the family in from the footer or a hub.
A hub took a ranking city page out of the top fifty (October 2026)
The hub gained a list of metros and began competing for the city's term.
The rule. One page owns each service-and-place search, and a check fails when a second page heads itself with it.
Demand for some services measured in five metros and nowhere else (September 2026)
The rule. A family may publish only the rows where demand measures.
The home metro was the worst-linked page in its own family (21 September 2026)
Its page lived outside the dataset, so the sibling rotation never reached it. Added to every sibling list, it went from 13 inbound links to 37.
The rule. The headquarters city is in every sibling list, as a row or a pinned entry; validate warns when it is not.
A family's median inbound link count predicted which pages went uncrawled (September 2026)
On 20 September 2026 one city family had a median of 298 inbound internal links and none of its 25 pages uncrawled; two others had a median of 5, with 2 and 13 of 25 never crawled. The orphans check had passed all three, because no page was at zero.
Linking every sibling took one city page from 5 inbound links to 28 and the family median from 5 to 27.
The rule. The orphans check reports each family's minimum and median inbound links and warns when either is under its floor; zero is not the only number that matters.
Structured pages
A numbers page read as a summary anyone could find (12 September 2026)
The figures were sourced and dated, and it still gave nobody a reason to cite it over the sources.
The rule. A statistics page carries a changelog and a refresh trigger, and a position on what the numbers mean; the statistics check fails one whose changelog is older than its newest figure.
Reading results
A page reported at #48 was #3 (October 2026)
The reading was national and the term was local, and a short results page looked like "not ranking".
The rule. Read city terms from the city; under sixty results is unreadable.
A city page read page one signed in, page two signed out (September 2026)
The rule. Positions are read signed out, by the tool.
A click drop that was not a ranking drop (September 2026)
Branded searches from a country where the company was recruiting inflated the month before.
The rule. Split brand from non-brand and filter to the target market before reading a trend.
Content agents
A draft explainer said a connector covered a product it does not (October 2026)
The rule. Every draft is fact-checked against its sources before a person sees it, and the mistake becomes a known-error rule the second time.
An agent filed a duplicate of a post its owner was already writing (October 2026)
It checked only its own "seen" list.
The rule. Check every state of the queue and the published posts before filing.
Visuals
639 images on 161 pages had no width or height (September 2026)
The article jumped under the reader as each loaded. Measuring at build time failed because the images lived in R2 with no local copy.
The rule. Image sizes are measured once into a committed manifest (heddle images) and the images check fails a built <img> that reserves no box.
A video embedded for a year was invisible to Search (9 September 2026)
No markup at all; and when it came, Search Console rejected a bare upload date.
The rule. A page that plays a video carries a VideoObject read off the film, with uploadDate as a date-time with its timezone, and the surface check fails one missing a field.
Operations
Share images went out with no Content-Type (October 2026)
A static Next export writes opengraph-image with no extension, and the host served every card on one of our product sites with no type; the gap audit of 11 October 2026 found it with curl -I.
The rule. The _headers writer types every extensionless image by its first bytes, one splat rule per file name, and warns when the file passes the host's 100-rule limit.
Merging was not deploying (September 2026)
A merged change was not live, and a link in an outbound email 404'd.
The rule. Deploy is its own step, and verification probes a string only the new build contains.
A page that ranks is not a page that helps (October 2026)
Google's spam policy on scaled content names pages generated to rank, and Google publishes no helpfulness score.
The rule. Every indexable page is read against Google's own helpful-content questions (heddle check, the helpful gate), with floors per kind of page and a baseline that only tightens; growing the baseline takes HEDDLE_HELPFUL_GROW=1 and a reason in the pull request.
Its blind spot. A draft that retells a vendor announcement passed every floor on one of our sites, so whether an explainer adds to its sources is still a person's call. Without the model token the gate reports SKIPPED, never PASS, and in CI (or with --require-model) heddle check fails on it.
Pages under the helpful floors were the ones Google left out (October 2026)
The first weekly re-score on one of our sites (October 2026) put each live page's helpful-content reading beside its Search Console inspection: 11 of 46 pages under a floor were not indexed, against 0 of 14 above.
The rule. The refresh agent re-reads every live page against the helpful questions once a week, keeps a short history of each page's score beside its index status, and lists the pages under a floor for a rewrite. It rewrites nothing itself.
Thin pages left out of the sitemap were still indexed (September 2026)
A case study migrated with a four-word body had been left out of the sitemap, yet three pages linked to it and an internal link is a stronger signal than a sitemap absence.
The rule. A page whose body is under the thin floor carries noindex, decided by its body, not by a slug list, so it comes back on its own once someone writes it. The meta check warns on an indexable thin page.
A prune cost clicks nobody had counted (September 2026)
Thirty posts pruned on 7 September 2026 cost 58 clicks a month, and 72 of the 84 clicks they had earned came from one developer how-to.
The rule. Before a page is pruned or redirected, read its Search Console clicks for the last 90 days; anything with clicks is rewritten or kept, not cut.
Share cards were crawled as pages (September 2026)
Google crawled all 128 Open Graph cards on one of our sites, and about twenty sat in Search Console under "crawled - currently not indexed" (19 Sep 2026).
The rule. heddle aeo sends X-Robots-Tag. Noindex on every share image and on /_next/static, and the canary checks it live with the card's image/* type. Social networks fetch the card directly and ignore the header.
The sitemap said every page changed on every deploy (September 2026)
Every lastmod was the build time, so six deploys in a day told Google 294 pages had changed six times (6d79ba3, 21 Sep 2026).
The rule. The surface check fails a sitemap whose every lastmod is the build date (surface.launched excuses launch day), a lastmod after the build, and a lastmod that disagrees with the page's own dateModified.
A UTC time moved an event to the next day (September 2026)
An evening meetup written in UTC read as the following day, and an AI Overview hedged its time (12 Sep 2026); the blog writer dated drafts in UTC, so anything after 5pm read as tomorrow (5c44d79).
The rule. A date with a time carries an offset, the offset of surface.timezone that day, and an Event's start has a time.
A Markdown twin answered differently from its page (October 2026)
City twins told an assistant something about the office that the pages did not (1db78ea, 11 Oct 2026).
The rule. agent-ready fails a twin whose prose is not on its page or whose heading is not the page's H1.
A GA4 linker multiplied every URL (September 2026)
_gl on every link between a host and its own subdomain filled Search Console with query-string variants (b923fe1).
The rule. The meta check fails tracking parameters on links to the site's own hosts, and _gl anywhere.
Well-formed links were dead (September 2026)
A docs host that was never created, a client domain that stopped resolving and an internal repository all passed every build check (748ab50).
The rule. heddle check --only outbound after any rename or batch of vendor links; never in CI, a redirect passes, and a failure must survive a slower retry.
Generated from the Heddle repository at ddb1b16.
Work with us
Let the agents bring you the leads.
Tell us about your business and who buys from you. On a short call we'll show you the searches your buyers make where you don't show up yet, and what the agents would do about them in their first month.
On the call, for your site
- The searches your buyers makeMeasured, with how many people make each one
- Where you show up, and where you don'tOn Google and in ChatGPT's answers
- The agents' first monthThe pages, fixes and links they would start with