We Checked 514 Paid Backlinks Overnight. 11.7% Were Flagged.
But 93 of the 95 link-related findings weren't deleted links. The anchor text had changed.
Note on naming: The client brands in this article are anonymised as Brand A through Brand I. The architecture, the checks and the numbers are from the production system. Publisher domains are left as-is, because they're public sites and they make the failure modes concrete.
TL;DR
- 514 paid placements are checked every night, automatically. On one night, 60 of them — 11.7% — were flagged.
- The failure is almost never a deleted link. It is rewritten anchor text: 93 of the 95 link failures were the phrase around the link changing, not the link itself.
- A report reaches each project's team before work starts, so detection moved from "whenever somebody happens to look" to the next morning.
The problem
A paid placement is bought once, then has to keep delivering every day afterwards. Publishers rewrite sentences, change headlines, add nofollow, retire pages, let domains lapse — and none of it triggers a notification. The placement stays in the budget as though it were still working.
The only way to know is to open the page and look. Across 13 projects, that meant 514 page-opens a day, by hand. That is not a process — it is a treadmill, and the moment it slips the business is paying for placements nobody has verified.
What the first run revealed
One night's run:
| Project | URLs checked | URLs with issues |
|---|---|---|
| A-FR | 156 | 21 |
| B-FR | 110 | 12 |
| E-FR | 69 | 10 |
| D-AU | 37 | 6 |
| 9 other projects | 142 | 11 |
| Total | 514 | 60 |
514 placements checked, 60 flagged — an 11.7% failure rate. About one in nine of the placements being paid for raised a problem that night.
That figure is a ceiling, not a precise count of damage. Some flagged pages are pages the scraper could not read rather than placements that definitely broke — that is the first row of the risk table below. Until the report separates failed from could not verify, treat 11.7% as the top of the range.
The more revealing half is how they failed:
| What went wrong | Count |
|---|---|
| Anchor text not found | 93 |
| Link not found | 2 |
| Page too large to check | 2 |
93 rewritten anchors against 2 removed links. Those 97 findings come from just 60 URLs — several pages had more than one anchor. The threat is not the publisher deleting the link — it is an editor rewriting the sentence the link sits in. A manual check asking "is the link still there?" would miss nearly all of it, because the URL is there and the link is there. Only the phrase that was purchased is gone.
That is the finding that changes the monitoring brief. It is the difference between buying a link and owning a placement.
The interesting failure
For this monitoring system, the link isn't the whole asset. The anchor is part of what was purchased.
When a publisher writes “casino en ligne” and points it at our URL, that phrase is what was bought: the words the reader clicks, and the words that carry the relevance. The URL is only where it points. So the failure that matters is not the link disappearing — it is the sentence around the link being rewritten while the link itself quietly stays in place.
That gives five things to verify, and only the first two are obvious:
| What we verify | Why it matters |
|---|---|
| The page loads | A dead page is a dead placement |
| The link is on the page | The obvious failure |
| The anchor text is on the page | The article was rewritten |
| The anchor is attached to our link | The phrase may be on the page, attached to someone else's link |
No nofollow / sponsored / ugc
|
A paid link can stop passing value without moving |
The last three are the checks most easily missed in a quick manual review. The third is what fired 93 times on that first night: the phrase we bought is simply no longer on the page. The fourth is subtler — the phrase can still be present while no longer belonging to our link, which is exactly what searching the page for the anchor would miss. And the fifth is invisible by definition, because nothing moves.
How the automation works
One n8n workflow, 262 nodes, with a separate pipeline per project. Each project gets its own hour, so the schedule itself keeps scraping inside the API's rate limit.
The same workflow on the n8n canvas: several of the thirteen project pipelines in one graph. Each cluster is the same nodes with a different project name on it — which is why a fix has to be applied thirteen times.
Google Sheets
↓
Scheduled audit
↓
Batch URLs
↓
Scrape
↓
Validate
┌─────┬─────────┬─────────────────────┐
↓ ↓ ↓ ↓
URL Anchor anchor in our link rel attrs
└─────┴──────┬──┴─────────────────────┘
↓
Result classification
↓
Google Sheets + Email
Results are written back to the spreadsheet, and each project's team gets one email listing only the failures. A 110-URL project with 12 problems produces a 12-row email, not a 110-row one. This is what that report actually looked like:
Twelve rows, one per placement that stopped matching. Nobody has to open anything else to know what to look at.
And a clean night produces the same email, with zero issues:
A quiet project still files a report. The headline reads All Clear, and the count is zero.
What it changed
Time. 514 manual page-opens a night, removed. At a rough 30–60 seconds per page by hand, that is 4–9 hours of checking a day — an estimate, not a measurement.
Time-to-detection. This is the change that matters most:
Before After
Publisher changes article Publisher changes article
↓ ↓
Weeks pass Nightly audit
↓ ↓
Someone manually checks Anchor mismatch detected
↓ ↓
Problem discovered Report arrives next morning
A placement edited today used to be found whenever somebody next happened to look. It is now found the same night.
Visibility. Every project now has a same-night record, including the quiet ones — “we found nothing” and “the report never arrived” are finally different messages.
Spend. Summing the recorded purchase price of the flagged placements gives 24,802 — and that covers 54 of the 60; six have no price in the workbook. Against a priced inventory of 223,990, that is 11.1% of spend tied up in flagged placements, almost exactly the 11.7% URL rate.
Every placement is a row. The price column is where the 24,802 above comes from — summed across all thirteen project sheets.
Scale. Each project gets a 60-minute window, and the throttle allows about four pages a minute — so a project can carry roughly 240 URLs before it stops fitting its slot, and A-FR is already at 156. Growth is a dial, not a rewrite, but it is not free.
What went wrong
The honest version of the above, in the form a plan needs:
| Risk | What it means | Impact | Effort | Owner |
|---|---|---|---|---|
| Some "missing link" alerts are really "we couldn't read the page" | The scraper can return an incomplete page, and the check calls it a missing link. At least 2 of the 60 were pages too large to read, and pages that need JavaScript are handled by a hard-coded domain allowlist today — so a site that changes how it renders produces a false alarm as well. More of the 93 may be unreadable pages rather than real edits. | Medium — trust in the report | Medium | TBD |
| The report can silently fail to send | Completion is detected from a hard-coded final row per sheet. Change the sheet and the audit still runs, but no email goes out. | High — reliability | Low | TBD |
| The scraping key is stored inside the workflow | It sits in 23 request URLs, so it travels with any export or share of the workflow. | Medium — security | Low | TBD |
| The validator exists in 13 near-identical copies | Every fix has to be applied thirteen times, and the copies drift. | Medium — maintenance | Medium | TBD |
| Diagnostics can land on the wrong URL | A report row can carry the previous row's explanation. | Low — noise while debugging | Low | TBD |
Two rows stand out. The first is about trust — a monitoring system that cannot tell "the placement broke" from "we never managed to check it" cannot be relied on, and the current output does not distinguish them. The second is the completion check: the highest-impact item on the list, and the cheapest to fix.
What we'd change before scaling
- Fix the completion check (high impact, low effort) — swap the hard-coded sentinel row for dynamic completion. The report can silently fail to send, which is the most serious item on the list and one of the cheapest to close.
- Rotate the exposed scraping key into credentials — now (low effort). It needs no funding, so it should not wait on any decision below.
- Move to three result states — verified, failed, could not verify — instead of today's pass/fail (medium effort). This is what turns the 11.7% figure from a ceiling into a number you can act on.
- Consolidate the thirteen validators into one (medium effort). It removes the largest maintenance cost in the system, and makes every future change a single change.
- Add a JavaScript fallback for suspicious pages (medium effort), so the false alarms behind the first risk row stop mixing with real removals.
- Decide who contacts the publisher, and what we ask for (the one item here that needs no engineering) — a correction, a replacement or a refund. The report says what changed; it doesn't yet say who acts on it.
If we were taking this into the next stage, we'd fix the first two immediately, then tackle the remaining three before increasing the inventory.
Final takeaway
The workflow started as a simple question — are the backlinks we paid for still there? — and the more useful question turned out to be: does the page still contain the exact placement we paid for, and can we prove we successfully checked it?
The links were usually still there. The anchor text was what changed. That one finding reshaped the monitoring brief: on a single night, 93 rewritten anchors against 2 genuinely removed links.
Which is why the recommendation is not “buy more links” or “check more often”. It is to make the report trustworthy — separate failed from could not verify, close the silent failures, and keep the anchor rather than the URL as the thing being monitored.
*How this is built: one n8n workflow of 262 nodes, with a separate pipeline per project. The engineering teardown — the validator, the code




Top comments (0)