---
title: "Keyword cannibalization checker · gscdump"
canonical_url: "https://gscdump.com/tools/cannibalization"
last_updated: "2026-10-03T04:31:35.311Z"
meta:
  description: "Free keyword cannibalization checker for Google Search Console. Lists queries where 2 or more of your pages get impressions, with the click split per page."
  "og:description": "Free keyword cannibalization checker for Google Search Console. Lists queries where 2 or more of your pages get impressions, with the click split per page."
  "og:title": "Keyword cannibalization checker · gscdump"
---

Which of my pages compete with each other for the same query?

# Free keyword cannibalization checker for Search Console

Read-only, on your own Search Console data: the queries where 2 or more of your pages each receive impressions over the last 28 days, with the click split and position spread.

## What it returns

Real rows, no sign-in

Each keyword with every nuxtseo.com page Google showed for it over the last 28 days.

[nuxtseo.com](https://nuxtseo.com) · 2026-08-22 to 2026-09-18, 8 pages of 36 queries · captured 2026-09-22

Example Cannibalization rows from nuxtseo.com

| Keyword | Competing page | Clicks | Impressions | Position |
| --- | --- | --- | --- | --- |
| |
| nuxtseo | / | 27 | 41 | 1.10 |
|  | /docs/nuxt-seo/getting-started/installation | 0 | 17 | 1.00 |
|  | /releases | 0 | 11 | 2.82 |
|  | /docs/nuxt-seo/getting-started/introduction | 0 | 27 | 1.19 |
|  | /docs/nuxt-seo/releases/v5 | 0 | 27 | 1.00 |
|  | /docs/sitemap/getting-started/introduction | 0 | 13 | 1.00 |
| nuxt-ai-ready | /docs/ai-ready/getting-started/introduction | 11 | 18 | 1.00 |
|  | /docs/ai-ready/getting-started/installation | 0 | 12 | 5.17 |

These are nuxtseo.com's own rows, read from its Search Console record. Connect a Site below to run the same query over yours.

## Run it on your own record

[**Continue with Google **](https://gscdump.com/auth/google)

HostedRead-only Search Console scope. Free during beta.

or

```
gscdump analyze cannibalization --site sc-domain:example.com
```

$ LocalMIT licensed, on npm.

Over MCP: `run-report { siteId: "<site-id>", reportId: "risks", comparison: "prev-period" }`

[Connect with MCP](https://gscdump.com/mcp) to reach it from ChatGPT, Claude, Cursor, or Copilot.

## **How the checker works**

Google's Search Analytics API reports one row per query and page. When two or more of your pages appear in the rows for the same query, they are competing for it. This query groups the last 28 days by query and keeps the groups with more than one page.

1. Read the query and page rows for the last 28 days from the Site's Search Console record.
2. Drop query-and-page rows with fewer than 10 impressions, where the numbers are too thin to compare.
3. Keep each query where 2 or more of your pages each reached the 10-impression minimum.
4. For each query, list the pages with their clicks, impressions, CTR, and average position, and measure the spread between the best and worst position.
5. Drop queries whose best and worst page positions differ by more than 10 positions.
6. Grade severity: 3 or more pages or 50 or more clicks split is high, 2 pages within 5 positions is medium, the rest is low.

The checker reads only data Google already reports to you. It fetches no page and needs no crawl, so a row means Google itself showed two of your URLs for the query.

A blog post titled "Best CRM software 2026" and a product page aimed at the same query is the usual shape. Google picks one per results page, so the clicks split, the links split, and neither page holds the position one page would.

## **What the split costs**

- **Split links.** Links that would point at one page point at several, and no page gets the full weight.
- **Split clicks.** Impressions land on whichever page Google shows that day, so no single page builds a CTR record for the query.
- **Unstable position.** Google alternates between the pages. The record shows this as a small spread with the position column moving week to week.

## **What to do with a row**

- **Merge.** Keep the page with the most clicks and links, move anything unique from the others into it, and 301 redirect the rest.
- **Canonical.** If the pages must all stay up, point the weaker ones at the strongest with `rel="canonical"`.
- **Separate.** If the pages answer different questions, retitle each so it matches its own query and no longer the shared one.
- **Noindex.** A thin page that exists for people and not for search can carry a noindex tag and stay reachable.

## Common questions

It reads the last 28 days of your Search Console record and keeps queries with 10 or more impressions where at least 2 of your pages received impressions. Each row lists the pages, their clicks, and the spread between their positions.

High: 3 or more pages, or 50 or more clicks split. Medium: 2 pages within 5 positions of each other. Low: everything else. It is a sort aid, not a verdict.

Yes. Two pages at a wide position spread is common and often harmless. The rows worth reading are the ones where several pages sit close together for a query with real clicks.

## **See also**

<dl>

<dt><a href="https://gscdump.com/tools/striking-distance">Striking distance keywords</a></dt>
<dd>Queries ranking 4-20 by impressions, with CTR and clicks for each.</dd>

<dt><a href="https://gscdump.com/tools/content-decay">Content decay</a></dt>
<dd>Pages whose clicks fell 20% or more against the previous 28 days, with the clicks lost.</dd>

<dt><a href="https://gscdump.com/tools/opportunity">Opportunity keywords</a></dt>
<dd>Queries whose CTR sits below the benchmark for their position, ranked by the click gap.</dd></dl>

Every day you're not syncing is data Google will delete.

Eligible Sites backfill available Search Console history. Data sources depend on the tool and account. Free during beta.

[**Join the waitlist **](https://gscdump.com/#get-access) [**Connect with MCP **](https://gscdump.com/mcp)

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
