WriteMySEO / Blog / Diagnosing Keyword Cannibalization From Query-URL Data
SEO data

Diagnosing Keyword Cannibalization From Query-URL Data

Two of your URLs ranking for one query is usually not a problem. Here's how to compute a real cannibalization signal from Search Console data and when to act on it.

Keyword cannibalization is the most over-diagnosed condition in SEO. The standard test — export your Search Console query-page report, find queries where more than one URL appears, declare a problem — flags hundreds of queries on any site with more than a few hundred pages. Most of them are fine. Some of them are pages Google is deliberately showing together.

The useful question is not "do two URLs rank for this query" but "is Google's uncertainty about which URL to serve costing me clicks." Those are different questions, and only the second one is worth a content merge. This post covers what Google actually does when several of your pages match one query, what Search Console's data model can and cannot tell you about it, and a computable signal that separates harmless overlap from real dilution.

What Google actually does when two of your URLs match one query

Three separate mechanisms are at play, and conflating them is where most bad diagnoses start.

Canonicalization. If two URLs are near-duplicates, Google picks one and folds the signals together. This is not cannibalization; it is the system working. You will see it in Search Console as one URL earning impressions and the other appearing under "Duplicate, Google chose different canonical" in the Pages report.

Host crowding limits. Google announced a site diversity change in 2019 that generally limits the number of results from a single site in the top results, with exceptions for cases where the algorithm judges more results from one domain to be especially relevant. The practical consequence: when several of your pages are eligible, they are not all competing for adjacent slots. One or two get through, the rest are filtered out of the visible SERP.

Per-query URL selection. For a single query, Google ranks documents, not sites. If two of your pages score close together, small day-to-day scoring changes can swap which one surfaces. That swap is visible in your data and it is what people usually point at as evidence of cannibalization. It is evidence of a close call, not necessarily of harm.

The reasonable inference — not documented behavior — is that a swap costs you something only when the alternating URLs perform differently. If both convert impressions to clicks at similar rates, which one Google picks is close to irrelevant to you.

What Search Console's data model hides

Before computing anything, know the constraints baked into the source.

A cannibalization signal you can actually compute

The signal has two parts: instability (does the winning URL change) and underperformance (does CTR sit below what the position would predict). You need both. Instability alone is noise.

Over the Search Console bulk export, per query and week:

WITH rows AS (
  SELECT
    query,
    url,
    DATE_TRUNC(data_date, WEEK) AS wk,
    SUM(impressions) AS impr,
    SUM(clicks) AS clicks,
    SAFE_DIVIDE(SUM(sum_top_position), SUM(impressions)) + 1 AS avg_pos
  FROM `proj.searchconsole.searchdata_url_impression`
  WHERE is_anonymized_query = FALSE
    AND search_type = 'WEB'
  GROUP BY query, url, wk
),
weekly_winner AS (
  SELECT query, wk,
    ARRAY_AGG(url ORDER BY impr DESC LIMIT 1)[OFFSET(0)] AS top_url,
    SUM(impr) AS impr, SUM(clicks) AS clicks,
    COUNT(DISTINCT url) AS url_count
  FROM rows GROUP BY query, wk
)
SELECT query,
  COUNT(DISTINCT top_url) AS distinct_winners,
  COUNT(*) AS weeks,
  SUM(impr) AS impr,
  SAFE_DIVIDE(SUM(clicks), SUM(impr)) AS ctr,
  MAX(url_count) AS max_urls_in_a_week
FROM weekly_winner
GROUP BY query
HAVING weeks >= 8 AND impr >= 500 AND distinct_winners >= 2
ORDER BY impr DESC

Then join the result to a CTR-by-position baseline built from your own data — median CTR for each integer position across the whole property. A query whose winning URL flipped three times and whose CTR sits well under your own baseline for its average position is a genuine candidate. A query that flipped but hits baseline CTR is not.

Building the baseline from your own property rather than a published curve matters. Branded queries, SERPs with AI Overviews, and verticals with heavy SERP features all have different CTR profiles, and an external curve will make half your site look broken.

Which pattern are you actually looking at

Once you have candidates, the fix depends on the cause. These are distinguishable from the data plus a look at the pages.

PatternData signalFix
Near-duplicate templatesBoth URLs rank, near-identical titles, one often flagged as duplicate canonicalConsolidate to one URL, 301 the other
Intent split across pagesDifferent URLs win for different query variants; CTR at baselineLeave it alone; strengthen the distinctions
Unresolved close callWinner flips weekly, CTR below baseline, no clear intent splitMerge, or make one page clearly the target and internally link to it
Filter or parameter leakageWinning URL includes query strings or facet pathsCanonicalize or block the parameter set
Pagination or archive pages surfacingPage 2+ or tag pages winning brand-adjacent queriesFix internal linking; make the hub the strongest candidate

Note the second row. Two pages ranking for overlapping queries with healthy CTR is a sign your site covers a topic at more than one level of specificity. Merging those pages reduces coverage and can lose you the long tail.

What to do with this

  1. Run the query on daily-grain data, weekly aggregated, with at least eight weeks of history. Monthly exports cannot show instability.
  2. Build your own CTR-by-position baseline from the same export, segmented at minimum into branded and non-branded.
  3. Rank candidates by impressions, not by count of overlapping URLs. A query with 50,000 impressions and one flip is worth more attention than a query with 200 impressions and six URLs.
  4. Check the Pages report before merging. If Google already consolidated the pair via canonicalization, there is nothing to fix and a 301 changes nothing.
  5. Treat merges as testable changes. Record the pre-merge CTR and impression baseline for the affected queries, and check whether the combined URL exceeds the better of the two originals. It often does not, and that result should change how aggressively you merge next time.

The general rule: cannibalization is a CTR problem masquerading as a URL-count problem. Measure the CTR.

Search Consolecannibalizationbigquerymeasurement

WriteMySEO produces marketing content, not legal, medical, financial, or compliance advice. Figures cited reflect publicly reported industry data at time of writing and shift over time.

Get started

We write this well about your industry, every month.

AI-drafted, human-reviewed SEO content on a flat subscription. Blog posts, metadata, schema, and internal links, shipped on a monthly rhythm.

See plans

More from the blog