Tag: SEO

  • We wrote a second checker for the space between articles. It caught two orphans on day one.

    We wrote a second checker for the space between articles. It caught two orphans on day one.

    Every automated check we had looked inside a single article. Links resolve, disclosures are present, no duplicate of anything published before. Nine checks, all of them scoped to one piece of writing at a time.

    Our three worst failures were all outside that scope. A sitemap frozen for ninety-three days. An article that went twenty-seven days without a crawl. A site with no internal links at all. Each individual article was fine. The site was not.

    So we wrote a second checker, at a different scale. This is what it looks at, what it found immediately, and where it runs.

    A diagram of three article boxes. The nine per-article gates wrap each box. The dashed lines running between the boxes mark the space where our worst failures lived.
    Nine checks guard each box. Nothing was watching the dashed lines.

    The six checks and where each one came from

    None of these are clever. Each exists because we lived through the thing it now catches.

    Is the sitemap current? Ours had been frozen since June. It was still advertising eleven pages we had deleted while listing none of the ones we had published since.

    Do the URLs in the sitemap resolve? Those eleven returned 404 to anything that followed them.

    How many article-to-article links exist? Across our English site the answer was six. On the Japanese site it was two, and both of those were between the same pair of posts.

    Which articles have nothing pointing at them? These are dead ends for a crawler. A reader who lands there has nowhere to go except back.

    Which articles point at nothing? The same problem from the other side.

    How old is the newest article? A site that has not published in a month is a different kind of broken, and nothing reports it.

    Six checks, a few hundred lines, standard library only. Writing it took about an hour, most of which was spent on the link graph.

    What it found

    The Japanese site had four articles with no article-to-article links in either direction. They had been that way since publication. All four were still linking correctly to legal pages, which is why a visual check had passed them for months — the links were there, they just went nowhere useful.

    Six site-level checks listed against the real failure each one came from. A sitemap frozen ninety-three days. Eleven URLs returning 404. Six article-to-article links. Four articles with nothing pointing at them. A newest article thirty-two days old.
    A checklist built from scars again, which is the only way these ever get written.

    Then it caught something while we were still working.

    We publish through a script. That script now runs the site checker immediately after a successful publish. On the first article we shipped after building it, the output read:

    Gates passed, article published, then a failure line: one article with nothing pointing at it. The article it was complaining about was the one we had just published, forty seconds earlier.

    We fixed it before the page had been crawled. The same thing happened again a few hours later with an article on the Japanese site. Two catches on the first day, both of which would otherwise have sat there until somebody noticed.

    Terminal output showing an article publishing successfully, then the site health check immediately reporting one article with nothing pointing at it. The article it flagged was the one just published.
    The first article we shipped after building it. The check was complaining about that very article.

    Where it runs

    Two places, for two different reasons.

    Immediately after every publish. A new article starts life with nothing pointing at it. That is the default state, not an unusual one, so the moment of publishing is exactly when the check is worth running. The site check does not block the publish and cannot undo it — the article is already live, and the check is telling you what to do next.

    Every morning at nine. Rot is not an event. The sitemap did not break on a particular Tuesday; it stopped updating and then stayed stopped for three months. Only a repeated check finds that kind of failure.

    The part that decides whether any of this works

    The checker writes a dated report to a folder. If that were the whole design, it would be worthless.

    A report nobody opens is not monitoring. It is a second copy of the original problem, because the entire failure mode we are trying to fix is information that existed and was never read. The sitemap was visible in a browser the whole time. Search Console would have answered the crawl question for anyone who asked it. Nobody asked.

    So the check raises a system notification when something fails. That notification is the actual product; the report is just where the detail lives.

    We verified that the notification appears. This sounds like an unnecessary step until you remember that the command to display one returns success whether or not the operating system shows anything, which is the same shape as a publishing API that returns 201 for an article that reaches readers as raw markup. An exit code describes the call. It does not describe what a person saw.

    What it cannot do

    It does not know whether an internal link is any good. A link exists or it does not; whether it was worth placing where it sits is a judgment. Nothing here stops you from satisfying every check with a block of related links at the bottom of each article, which passes the counter while helping nobody.

    It also has no opinion about whether the articles are worth reading. That was true of the per-article gates as well. Both checkers clear the floor so the attention goes somewhere that needs it.

    If your site is small

    You can run the first three checks by hand in under two minutes, today, without writing anything.

    Open your sitemap in a browser. Look at the date on it, then click two or three of the URLs inside.

    Take your newest article and inspect its URL in Search Console. Not the ranking. Whether it has been crawled at all.

    Open any article and try to reach a different one by clicking. If you cannot, a crawler cannot either.

    If all three pass, you do not need a checker yet. If any of them fails, you have learned something more useful than a month of traffic data would have told you.


    Editorial note. Written and edited by the operator of this site. The counts, the dates, and the day-one results are from our own two sites and our own tooling, recorded on 2026-09-15.

    Disclosure. This article contains no affiliate or sponsored links. This site may earn commissions from links in other articles, and those articles carry their own disclosure at the top. Nothing here is professional advice.

  • Fifteen months. Zero revenue. The measurement was never actually running.

    Fifteen months. Zero revenue. The measurement was never actually running.

    Here is the whole of it. Between June 2025 and August 2026 this site earned nothing. Not a small amount. Zero confirmed commissions, zero conversions, across fifteen months of an affiliate programme we had been approved for and had linked from live articles the entire time.

    That number is easy to explain away. New site, hard niche, not enough articles. All of those were true, and all of them were beside the point, because when we finally audited the site properly in September we found something worse than failure. The experiment had never been running.

    What the dashboard said

    Search Console, for the five weeks to September 10: fourteen impressions. Zero clicks. Average position 52.6, which is page five or six of the results. Nine pages indexed, twenty not.

    Read quickly, that is a story about quality. The articles are not good enough to rank, so they sit on page six, so nobody clicks. Write better articles, wait longer.

    We read it that way for months.

    What was actually true

    Three things, all found in a single afternoon of looking at the plumbing rather than the numbers.

    The sitemap had been frozen since June 9. Three months. It was still advertising pages we had deleted — eleven URLs returning 404 — while listing none of the articles published since. Of the twenty pages Google had not indexed, eleven were pages that no longer existed. We had been feeding a crawler a map of a site that was not there.

    An article published on August 14 had never been crawled. Not ranked badly. Not crawled at all. URL inspection returned no record of a visit, three and a half weeks after publication.

    There were no internal links. Zero, across every article on the site. No path from any page to any other page. Each article sat alone with nothing pointing at it and nothing leading away.

    Any one of these would depress the numbers. Together they mean the fourteen impressions were not a measurement of anything. They were the reading you get from an instrument that is unplugged.

    Two columns comparing what the dashboard reported with what was true. The dashboard showed 14 impressions with zero clicks. The site meanwhile had a sitemap frozen since June 9 advertising 11 dead URLs. No tool raised an alert.
    The same five weeks, read two ways. Only the right-hand column explains the left.

    The part that is uncomfortable to write

    All three failures were silent. No error, no alert, no red number on a dashboard. The sitemap plugin did not announce that it had stopped. Search Console does not tell you that an article is uncrawled unless you inspect that specific URL by hand. Nothing anywhere reports “this site has no internal links.”

    Three site failures shown as bars by how long each went undetected. The sitemap was frozen for 93 days. An article went uncrawled for 27 days. Internal links were missing for the life of the site.
    How long each failure ran before anyone noticed. No tool reported any of them.

    And all three were visible to anyone who looked. Not one required special tooling. Opening the sitemap in a browser takes four seconds and would have shown a file with a June date and eleven dead URLs in it.

    Nobody looked, because the numbers were being reported every week and the numbers looked like a story we already understood. A bad number that fits your theory is more dangerous than no number at all. It closes the question.

    The arithmetic we should have done first

    Once the plumbing was fixed, we finally did the sum we had been avoiding for over a year.

    The affiliate programme pays roughly ¥100 per click on the products we were approved for, measured from our own account. Conversion runs near 0.8%. So one confirmed sale needs about 125 clicks on an affiliate link. At a 7% click-through from article to link, that is about 1,800 sessions for a single sale.

    The original goal was ¥1,000,000 a month. Run the same numbers forward and that requires roughly 135,000 sessions a month, every month, for a payout model that resets to zero on the first of each month. We had six articles.

    The calculation chain from earnings per click of 100 yen through a 0.8 percent conversion rate to 1800 sessions per sale. A target of one million yen a month requires 135000 sessions every month.
    Fifteen months of work could not tell us the plan was unreachable. Twenty minutes with a calculator did.

    This is not a stretch target. It is a different business, and no amount of writing better articles was going to close a gap of that size.

    The useful thing about doing the arithmetic is that it is cheap and it is final. Fifteen months of effort could not tell us the plan was unreachable. Twenty minutes with a calculator did.

    What changed as a result

    We stopped chasing the volume model. A payout that resets monthly means every month starts at zero no matter how much you published last month; the only way up is more traffic, forever. The alternative is recurring commission, where each referral keeps paying while the customer stays subscribed, so the work accumulates instead of evaporating.

    Under the recurring model the traffic requirement drops by more than an order of magnitude, because you are adding to a base rather than replacing it. Choosing which recurring programme turned out to be its own problem: our first application was rejected six minutes after we sent it. That is the business we are now building, in English, on this site. Whether it works is an open question. What is no longer open is whether the previous plan could have worked.

    We also changed how we measure. Two rules now:

    Check the instrument before reading it. Before any monthly number goes into a report, someone confirms the sitemap is current, spot-checks that recent articles have been crawled, and confirms internal links exist. Under a minute. It would have caught all three failures in June.

    A bad number gets audited, not explained. The temptation with a disappointing metric is to reach for a reason. The reason is usually available and usually plausible. The rule now is that an unexpected number is treated as a possible instrument fault until the instrument has been checked.

    If you run a small site

    The failure here was not strategic. We did not pick the wrong niche and lose fifteen months to it, although we did also pick a hard niche. The failure was that we spent fifteen months collecting readings from equipment nobody had verified was connected, and then reasoning carefully about those readings.

    Three checks, none longer than a minute:

    Open your sitemap in a browser. Look at the date. Look at whether the URLs in it still resolve.

    Take your most recent article and inspect the URL in Search Console. Not “how is it ranking” — has it been crawled at all.

    Pick any article and try to click your way to another one. If you cannot, neither can a crawler.

    We have described the gates that now run before anything publishes. Those catch problems inside an article. None of them would have caught any of the three failures above, which lived between the articles rather than inside them. That gap is the next thing we are building for. It turned out to be wider than we thought: the same gates later passed three articles that reached readers as raw markup.


    Editorial note. Written and edited by the operator of this site. Every figure here is from our own affiliate account, our own Search Console property, or our own audit notes of 2026-09-10. The revenue figure is not rounded.

    Disclosure. This article contains no affiliate or sponsored links. This site may earn commissions from links in other articles, and those articles carry their own disclosure at the top. Nothing here is professional advice.

  • We built an 8-gate checker for AI-drafted articles. The first run failed our own live site.

    We built an 8-gate checker for AI-drafted articles. The first run failed our own live site.

    Google’s guidance on scaled content abuse draws the line in a place a lot of people misread. It is not about whether a machine wrote the draft. It is about whether a person actually exercised judgment before it went live. That distinction sounds reassuring until you try to prove it. What does “a person reviewed this” look like six months later, when the only evidence is that someone remembers skimming it?

    We run a small publisher where the drafts are machine-written and the decisions are not. We have written before about what breaks when you hand the work to agents, and this is the control we built afterward. In September we stopped relying on memory and built a checker: eight gates, every article, fail-closed. Nothing publishes unless all eight pass.

    Then we pointed it at our own live site, which had seven published articles on it. It failed six of them.

    What the eight gates check

    The gates are deliberately boring. Each one exists because something specific went wrong, either to us or to someone whose postmortem we read.

    G-1: every outbound link resolves. A HEAD request to each URL in the body. Link rot is slow and invisible, and a dead link in a comparison article is the reader’s last impression of you.

    G-2: every commercial link points to an approved program. The article can only link to advertisers we have an actual approved relationship with. On our English site, where we have no approved programs yet, this gate blocks commercial links entirely rather than trusting a future editor to remember that.

    G-3: no banned expressions. A pattern list: income promises, absolutes, manufactured urgency. More on how badly this one behaved in a moment.

    G-4: not a near-duplicate of anything already published. Sequence similarity against the live corpus, pulled from the CMS at check time rather than from a local index that drifts.

    G-5: commercial relationships are disclosed above the fold. Only fires when G-2 found a commercial link, and then it requires the disclosure inside the first 400 characters, not in a footer.

    G-6: editorial responsibility and disclaimer are both present. Who stands behind this, and what it is not.

    G-7: no generation artifacts. Stray model chatter that survived into the draft.

    G-8: dates are sane. A surprisingly common failure: an article published in 2026 that confidently discusses “this year’s” pricing from 2024.

    Terminal output of the publication gate run for this article, showing all eight checks passing and the post being published as post_id 70.
    The gate run that published this article. A single failure writes the post as a draft instead; there is no flag to skip a check.

    What the first run found

    Six of seven live articles failed, and the failures were not subtle.

    One article carried an income figure in its own title, a specific monthly yen amount presented as an outcome. It had been sitting on the front page for weeks. Nobody had decided to publish that claim; a draft had simply never been argued with.

    Three articles were near-duplicates of each other. Same topic, same structure, marginally different phrasing, all three indexed and competing with each other for the same query. That is the exact pattern the scaled-content guidance describes, and we had produced it without noticing, because each one looked fine on the day it was written.

    Seven of seven were missing any link to our own disclosure and editorial pages. Those pages had existed since June. Not one article pointed at them. Every individual article had been reviewed by a person; the property as a whole had been reviewed by nobody.

    Separately, and outside the gates, we found the sitemap had been frozen since June 9 and was serving eleven URLs that no longer existed.

    None of this required sophistication to find. It required something that looks at every article the same way every time, which is precisely the thing a human reviewer stops doing around article four.

    The gates were wrong before they were right

    The first version of G-3 was close to useless, and this is the part most write-ups skip.

    It flagged a Japanese headline meaning roughly “the fundamentals, so you don’t fail” as a no-risk claim. It is not a claim about risk; it is an ordinary way to title an explainer. It flagged an article about selling AI prompts because the word “prompt” appeared in our list of generation artifacts. It flagged the phrase “right now” in a sentence where nothing was being sold.

    On the English side the pattern list had the same disease in a different accent. Early drafts of the rules would have flagged a sentence stating there is real risk in unattended automation, because it contained the word risk near a negation. They would have flagged “the server costs twelve dollars a month” as a price claim and “the site earned zero” as an income claim. Those are the sentences we most want to be able to write.

    Table of three real false positives from the first rule set: a headline about fundamentals flagged as a no-risk claim, an article about selling AI prompts flagged as a model artifact, and a quoted reader sentiment flagged as urgency.
    Three real false positives from the first rule set. Every one of them is a sentence we wanted to be able to write.

    So we narrowed the rules and wrote tests that assert non-detection. Fifty tests now, and a meaningful share of them exist to prove the checker stays quiet on honest sentences. The fixtures are real headlines from our own deleted drafts, not invented examples.

    This matters more than the detections do. A checker with a high false-positive rate does not get tuned. It gets bypassed, and then it is worse than nothing, because the bypass becomes the habit and the green checkmark becomes a lie.

    Three test strings posted to the site: a plain greeting returns 201, while a comma-separated list inside quotation marks returns 403, blocked by an SQL injection firewall rule.
    A separate failure, found the same week: the host firewall read an ordinary English list as an SQL injection and refused three paragraphs of this article. Bisecting the post paragraph by paragraph isolated it. The full account of that week is here.

    What it does not do

    The gates cannot tell you whether an article is worth reading. They cannot detect a confident factual error, an outdated recommendation, or a comparison that quietly favors the advertiser paying the most. Every one of those still requires a person who knows the subject.

    What the gates do is clear the floor, so that the human review is spent on judgment instead of on checking whether the links work. That is the whole argument. Automated checks are not a substitute for editorial oversight; they are what makes the scarce oversight land somewhere useful. We learned how narrow that floor really is a few days later, when all eight gates passed three articles that reached readers as raw markup.

    If you want to build one

    You do not need a framework. Ours is a few hundred lines of Python using only the standard library, and it runs in under a minute against the live CMS.

    Start with the failure you have already had. If you have shipped a dead link, write G-1 first. Run it against your existing published articles before you write another word, because the archive is where the evidence is, and it will tell you which gates you actually need.

    Then make it fail closed, and resist the urge to add an override flag. The moment there is a documented way to skip the gates under deadline pressure, the gates describe your intentions rather than your output.

    We are about seven weeks into this and the checker has caught things a human review already passed, more than once. That is not an argument that the humans were careless. It is an argument that reading an article and auditing an article are different tasks, and only one of them gets harder the more articles you have.


    Editorial note. Written and edited by the operator of this site. Every figure here comes from our own systems and is reproducible from our logs. Where we describe a failure, we found it on our own property, not someone else’s.

    Disclosure. This article contains no affiliate or sponsored links. This site may earn commissions from links in other articles, and those articles carry their own disclosure at the top. Nothing here is professional advice.