Detect a PBN Link Attack When Ahrefs' Spam Flag Misses It
Ahrefs' spam flag lagged during an active PBN attack on my brand. Here's the rank-vs-traffic heuristic that detected the link attack in hours, not weeks.
By Mike Hodgen
The Attack I Almost Didn't See
The rankings on one of my head keywords started slipping. Not a cliff, more like a slow leak. Position 3 became 4, then 6, then it fell off the first page entirely over about ten days.
My first instinct was the obvious one: Google shipped a core update and my DTC fashion brand got caught in the blast. That happens. You ride it out, you don't panic.
So I opened Ahrefs to confirm. I filtered the backlink profile by is_spam=true, expecting to see a wall of garbage. The report came back nearly clean. A handful of flagged links, nothing that explained a multi-position drop on a money keyword.
That clean report was the trap.
Because here's what was actually happening. Two separate PBN vendors were placing toxic links pointed at my domain. Every single day. New domains, fresh links, a coordinated push to drag my authority signals down and tank my rankings. And the standard spam detection missed both of them completely.
This is the thing nobody tells you about how to detect a PBN link attack: the paid tools that you trust to flag this stuff are built to catch yesterday's attack, not today's. The classifier said everything was fine while my revenue on that keyword bled out.
I run a brand that sells handmade products out of San Diego. I do not have a security operations center. What I had was 22,000 lines of Python and a stubborn refusal to accept that a clean spam report meant a clean backlink profile.
It took me about a week to figure out why the tools lied to me. The fix took two days. Here's the whole thing.
Why Ahrefs' Spam Flag Lagged on a Live Attack
I want to be clear up front: this is not me dunking on Ahrefs. I pay for it. It's an excellent tool and I'd buy it again tomorrow. The lag I'm about to describe is structural. Any spam classifier built on known signatures has the same blind spot.
Ahrefs spam-flag detection lag vs structural signal
The is_spam flag is trained on known patterns
The is_spam flag works the way most classifiers work. It recognizes patterns it has already seen. Ahrefs crawls billions of pages, identifies the footprints that PBNs leave behind (the templates, the hosting fingerprints, the interlinking shapes), and flags new domains that match those known patterns.
When the pattern is established, the flag is great. It catches the lazy spam, the recycled networks, the vendors running the same tired footprint they've used for three years.
Fresh PBN templates haven't been classified yet
The problem is the word "known."
When a PBN vendor spins up a batch of fresh domains on a new template, the classifier hasn't seen enough of that footprint to flag it yet. It needs volume. It needs the same shape to appear across enough sites before the model is confident enough to call it spam.
That confidence takes time to build. Weeks, sometimes longer.
In my case, both vendors were running templates new enough that the spam flag returned near-zero. Two concurrent attacks, both invisible to the classifier, because the classifier was waiting for a pattern that hadn't crossed its detection threshold.
This is the ahrefs spam detection lag in plain terms: by the time the flag catches up, the links have been live for weeks and your rankings have already moved. The tool will eventually be right. It just won't be right in time to help you.
If your entire defense depends on a classifier trained on known signatures, you are by design always one step behind a competent attacker. The fresh attack lives in the gap before the model learns the footprint. You need a signal that fires on the attack's structure, not its reputation.
The Trap of Net Referring-Domain Count
The spam flag was the first failure. The second one was more dangerous, because it actively reassured me.
Net referring-domain count masking the attack
The standard health-check metric everyone watches is net referring domains. Total count of domains linking to you, tracked over time. The logic seems sound: links go up, you're healthy. Links go down, you investigate.
During the active attack, my net referring domain count went from roughly 1,024 to about 1,020.
It dropped. By four. A rounding error.
If you were watching that number on a dashboard, you'd see a slow, gentle, completely normal-looking decline. Nothing about it would make you reach for the fire alarm. It looks like the natural churn every backlink profile has.
Here's why it lied.
Old, legitimate links were aging off the index. Sites going dark, pages getting removed, links naturally decaying the way they always do. That's normal attrition, and it was happening at roughly the same rate as always.
Meanwhile, toxic PBN domains were being added daily. New, fresh, poisonous.
The two flows roughly canceled out. Legitimate domains aging off, toxic domains coming on, and the net total barely moved. So the one metric I was watching to gauge backlink health showed me a placid little decline while a coordinated attack was loading new domains onto my profile every 24 hours.
Net count is a lagging, masking metric. It is the average of two opposite forces, and the average hides the very thing you need to see.
The lesson I took from this, and the conceptual core of how I now monitor everything: never watch the net total. Watch the velocity of new domains added.
A profile that loses four legitimate links and gains forty toxic ones nets out to plus thirty-six, or if the timing is unlucky, minus four. Either way the net number tells you nothing. The number of NEW domains appearing per day tells you everything.
Once I stopped looking at the total and started looking at the inflow rate, the attack became obvious. The masking only works on a metric that sums opposing flows. Break it into directional components and the manufactured velocity jumps right out.
The Signal That Actually Fired: High DR, Near-Zero Traffic
So I threw out net count and built the query that should have existed from day one.
Query domains, not individual links
First decision: surface referring domains, not individual links. Link-level analysis missed the attack too, because the volume of individual links was noisy and the spam flag was applied at the link level. Rolling up to the domain level cut through the noise and let me sort by something useful: first_seen.
I pulled every referring domain, ordered by when it first appeared, newest first. Now I was looking at exactly the domains that landed during the ranking drop.
Filter to DR >= 25 AND organic traffic <= 10
Then I applied the filter that turned a wall of data into a confession:
The DR vs Organic Traffic mismatch fingerprint
Domain Rating >= 25 AND organic traffic <= 10.
That combination is the fingerprint of a paid link farm, and it's nearly impossible to fake your way out of.
Think about what each half means. A real site with a Domain Rating of 25 or higher has earned authority. And a site that has earned genuine authority earns organic traffic as a byproduct. People search for it, land on it, link to it because it's useful. DR and traffic move together on legitimate sites.
A PBN breaks that relationship. It inflates DR artificially through interlinking, building a fake authority signal by having its own network of junk sites point at each other. But it generates essentially zero real search traffic, because nobody searches for a PBN and nobody lands on one on purpose.
High authority signal plus near-zero traffic equals manufactured. That mismatch is the rank-vs-traffic heuristic, and it is the single cleanest tell for a high DR zero traffic backlinks attack.
The beautiful part: this fires the same day the domains appear. It doesn't wait for a classifier to learn a footprint. It doesn't need a reputation database. It reads the structural contradiction baked into every PBN domain (authority without audience) and that contradiction is present from the moment the domain goes live.
When I ran that filter, dozens of domains lit up. DR 28, DR 31, DR 26, every one of them with single-digit or zero organic traffic, all first seen within the same two-week window. Two vendors, two footprints, one obvious shape once I stopped trusting the spam flag and started trusting the math.
The lagged classifier never stood a chance against a filter this simple. That's the whole point.
Two Leading Signals That Catch It in Hours
Finding the attack after the fact is forensics. I wanted early warning. So I added two leading signals that catch this in hours instead of weeks.
Two leading signals correlating to confirm an attack
Referring-domain count velocity alarm
The first is a refdomain velocity alarm, and it's the direct fix for the net-count trap.
Instead of watching the total, it watches the rate of NEW domains appearing per day. A normal week for my brand adds a handful of new referring domains organically. Maybe two or three, picked up from press, partner sites, the occasional blogger.
An attack spikes that rate hard. Eight, twelve, twenty new domains in a day. The alarm doesn't care about the net total at all. It only watches the inflow, and an abnormal inflow trips it within a day of the attack starting. This is what proper backlink velocity monitoring looks like: directional, not net.
Daily rank-velocity tracking with a SERP scraper
The second is daily rank-velocity. I pull my head-keyword positions every single day through a SERP-scraping API, so a rank drop shows up in 24 hours instead of whenever I happen to open Ahrefs and notice something feels off.
A daily rank checker means I see position 3 become position 5 the next morning, not next month. Combined with the velocity alarm, I now know within a day if rankings are moving AND whether suspicious domains are flooding in at the same time.
That correlation is the whole signal. Rankings dropping plus new-domain velocity spiking plus those new domains matching the DR/traffic mismatch equals an active negative seo detection event, caught in hours.
These two signals feed the AI system that fights back daily, which is the standing layer that acts on them automatically.
And critically, before you assume any ranking drop is an attack, rule out the boring explanation first. If the velocity alarm is quiet and no DR/traffic-mismatch domains appeared, you're probably looking at a core update, and you can prove it was the algorithm, not your site instead of chasing ghosts.
If the Paid Tools Miss It, How Would AI Know Where to Look?
This is the fair question, and I'll give you the honest answer: AI doesn't magically know where to look.
Data primitive vs custom judgment layer architecture
The intelligence here is not a model guessing at threats. If I asked Claude "is my site under attack," it would have no idea. It has no access to my backlink profile and no instinct for my normal velocity.
The intelligence is that I encoded the heuristic once. High DR plus near-zero traffic. Velocity over net count. Correlate with daily rank movement. I wrote that judgment down as logic, and now a daily job runs it against fresh backlink and rank data automatically and pings me the moment it trips.
The tool gives me the raw data primitive: the backlink records, the DR figures, the traffic estimates, the SERP positions. My custom logic on top catches exactly what the tool's own classifier misses.
That's the pattern across all 15-plus systems I've built. Pay for the data primitive. Build the judgment layer yourself. The off-the-shelf product optimizes for the average case, because that's what a product has to do. Your specific attack lives in the edge case the vendor hasn't trained on yet.
I'll be honest about the limit, because pretending otherwise would be exactly the kind of overpromise that gets vendors fired. This system catches the footprint. It does not auto-disavow. When the alarm trips, a human (me) still reviews the flagged domains before anything goes into a disavow file. Disavowing the wrong domains can hurt you, so that step stays manual on purpose.
The AI finds the attack. The human decides what to do about it. That division of labor is the right one.
Build the Detection Before You Need It
Here's the brutal part of a PBN attack. By the time your rankings visibly drop and your revenue dips enough that you go hunting, the damage has been compounding for weeks. The toxic domains have been live, aging into your profile, dragging your authority signals the whole time.
The window to catch it is before the net-count metric ever moves. Before the spam flag catches up. Before you lose a single position you'd actually notice.
Most brands don't have anything watching new-domain velocity and the DR/traffic mismatch on a daily basis. They have a dashboard showing net referring domains, which we just established is the one number engineered to hide exactly this. So they find out the hard way, after the loss, when forensics is the only option left.
I build these monitors as a standing layer, not a one-time audit. An audit tells you what happened. A standing monitor tells you it's happening, today, while you can still respond.
If you run a brand that ranks for terms worth attacking, someone can buy 80 spam domains and point them at you for the price of a nice dinner. You want the leading signals wired up before that happens, not after.
If that's you, let's build the monitoring before you need it.
Want to explore what AI could do for your business?
Book a free 30-minute strategy call. No pitch deck, no sales team, just a real conversation about your operations and where AI actually fits.
Get AI insights for business leaders
Practical AI strategy from someone who built the systems — not just studied them. No spam, no fluff.
Hodgen.AI
Ready to automate your growth?
Book a free 30-minute strategy call with Hodgen.AI.
Book a Strategy Call