Cannibalization & consolidation
Keyword-to-Page Mapping: How to Give Every Search Intent One Page
How to build a keyword map that assigns each search intent to one page, using Search Console and the live results page to group queries, a map template with status codes, and the routine that keeps new content from competing with old.
8 min read
A keyword-to-page map assigns every search intent your site wants to serve to exactly one URL. It is the document that stops a new article from competing with an old one, tells writers which page to improve instead of starting another, and shows where you have no page at all. This guide shows how to build one from Search Console and the live results page, with a test for deciding when two queries belong on one page, a map template with status codes, a worked example with messy real-world overlaps, and the routine that keeps the map true.
Most keyword mapping advice stops at a spreadsheet of keywords and target URLs. The hard parts are the ones in between: deciding which queries are really the same need, handling the pages you already have, and keeping the map current after merges and launches. Those are the focus here. If you are already dealing with pages competing for the same searches, read how to find and fix keyword cannibalization alongside this.
What a keyword map is, and what it is not
The unit of a good map is not a keyword but an intent: a group of queries that one page can fully answer. “Expense policy template”, “expense policy example” and “sample expense policy” are one intent. Google’s SEO Starter Guide says you do not need every variation of a phrase on a page, because its language matching can relate similar wording. So “one keyword per page” is the wrong rule: one intent per page is the right one.
A map is also not a keyword density plan. Google does not use the keywords meta tag, and repeating phrases unnaturally is keyword stuffing, which its spam policies name. The map says which page owns an intent; the page itself should then simply answer it well.
Step 1: Collect the queries
Start with demand you already have, then add demand you do not:
- Search Console, query and page together. Pull query-and-page pairs for the last three to twelve months through the Search Analytics API, Looker Studio or the BigQuery export; the interface export gives separate tables, capped at 1,000 rows. These pairs show which page Google currently uses for each query, which is the starting point of the map.
- Remove branded queries with Search Console’s branded filter where your site is eligible, or a regex filter on your brand names. They map to your homepage and product pages on their own.
- Add research for what you do not rank for yet: a keyword tool, competitors’ pages, and the questions sales and support hear every week.
Expect the Search Console list to be incomplete at the long tail: Google leaves out queries issued by very few people, as its deep dive on performance data explains. That does not matter much for a map, which works at the level of intents, not individual phrasings.
Step 2: Group queries by intent, using the results page
Two queries belong on the same page when searchers mean the same thing by them, and the best evidence for that is what Google shows. Search both queries in the same market and compare the top ten organic results.
| Shared URLs in the top 10 | Rule of thumb |
|---|---|
| 4 or more | Same intent: one page. |
| 1 to 3 | Look closer. Same format and same kind of page at the top? One page. Different formats, such as templates for one and guides for the other? Two pages. |
| None | Different intents: two pages, or one query you do not need. |
The thresholds are ours, not Google’s; tune them on a sample of groups you are confident about. Two more checks before you lock a group:
- Same format? If one query’s results are tools and the other’s are articles, they need different pages even with some URLs in common.
- Same reader? Beginners and experts often search the same topic with different words, a point the SEO Starter Guide makes too. If the results for the beginner phrasing are explainers and the expert phrasing gets reference material, consider two pages.
One page or two?
Do the two queries share 4 or more top-10 results?
Do they share at least one, with the same format at the top?
Is there a different reader or task behind each?
Step 3: Assign each intent to one URL
For each group, write down the page that should own it and the page that does own it today, from the Search Console pairs. The comparison gives every row a status:
| Status | Means | Usual action |
|---|---|---|
| On plan | The intended page ranks | Keep; strengthen if it ranks low |
| Split | Two or more of your pages take turns | Differentiate or merge |
| Off plan | A different page from the intended one ranks | Point internal links and anchors at the intended page, or change the plan if Google’s choice is better |
| Weak | The intended page exists but barely ranks | Improve the page; check it matches the intent |
| Gap | No page serves the intent | Brief a new page, if the intent is worth it |
| Retired | The page was merged or removed | Record where the intent now lives |
“Off plan” deserves a second look before you act. Sometimes Google has picked the better page, for example a detailed guide over a thin product page for an informational query. Then the right fix is to the map, not the site.
The map template
One row per intent. Copy these columns into a spreadsheet:
| Column | Example |
|---|---|
| Intent (named after the main query) | expense policy template |
| Other queries in the group | expense policy example; sample expense policy |
| The reader is trying to… | …get a policy they can adapt for their company today |
| Format the results page rewards | Downloadable template with a filled-in example |
| Intended URL | /blog/expense-policy-template |
| Ranking URL today | /blog/expense-policy-template |
| Status | On plan |
| Supporting pages | /blog/per-diem-policy (links to the template) |
| Clicks and position, last 3 months | 2,940 · 3.4 |
| Owner | Content team, finance topics |
| Last checked | Date of the last results-page check |
Join it to your content inventory on the URL. The inventory says what each page is; the map says what it is for.
Worked example
An illustrative example, not client data. A payroll software company maps its payroll topic and finds six intents across eight existing pages:
| Intent | What the data showed | Decision |
|---|---|---|
| payroll software small business | Pricing page and a blog post take turns, both around position 9 | Split. Pricing page owns it; the post is refocused on “running payroll for the first time” and links to pricing |
| payroll denmark | The guide ranks 2nd and gets most clicks | On plan; keep |
| holiday pay calculator | Calculator ranks 1st | On plan; keep |
| paysuite alternative | A post about switching ranks instead of the comparison page | Off plan. The post is a better answer to “switching”, not to “alternative”. Re-point anchors to /vs/paysuite and keep the post for its own intent |
| payroll calendar | Two old posts, one per year, neither in the top 20 | Weak and split. Merge into one evergreen calendar page updated each year |
| payroll checklist | No page; the results page shows checklists and templates | Gap. Brief a new checklist page |
Note what the map did. It produced one new page, one merge, two re-pointing jobs and two pages left alone. Without it, the likely outcome was a new “payroll software for small businesses” article, a third page competing for the first intent.
Step 4: Turn the map into work
- Split rows go to the cannibalization process: decide between differentiating and merging. For merges, follow how to merge pages without losing rankings.
- Off-plan rows usually need internal links. Make sure the pages that link to the topic use anchor text that describes the intended page, and link to it rather than to the page Google picked by default.
- Weak rows go to the refresh queue, with the intent and format from the map in the brief.
- Gap rows become briefs, ranked by demand and business value. See how to write a content brief.
Keep the map alive
A map is only useful while it is true. Four habits keep it that way:
- Check it before every brief. If the intent already has a page, the brief is a refresh, not a new article.
- Update it after every merge, redirect or launch, on the same day, as part of the launch checklist.
- Compare it with Search Console quarterly. New split and off-plan rows are early cannibalization warnings.
- Re-check the results page for the top intents once or twice a year. Intent shifts, and with it the format and sometimes the right page.
Common mistakes
- Mapping keywords, not intents, which produces one thin page per phrasing.
- Grouping by word similarity alone. “Payroll checklist” and “payroll calendar” share a word and nothing else.
- Ignoring existing pages, and mapping as if the site were empty.
- Forcing Google’s hand when its chosen page is the better answer.
- A map nobody checks before commissioning content.
Where Morrison fits
Morrison connects to Search Console and reads query-and-page data, so chat can show which of your pages rank for which queries and where two pages split a query. It checks live Google results through SerpApi to compare what ranks for two queries, and its site index records a page type and search intent for every URL. Upload your existing map as a spreadsheet and ask which rows are off plan, as in the film above. See keyword-to-page mapping.
Key takeaways
- Map intents, not keywords: one group of queries that one page can fully answer, one URL.
- Let the results page group queries: shared top-10 results and the same format mean one page.
- Give every row a status by comparing the intended page with the one ranking today.
- Make the map a gate: checked before every brief, updated after every merge and launch.
Sources and further reading
- 1SEO Starter GuideGoogle Search Central
- 2How to specify a canonical URL with rel="canonical" and other methodsGoogle Search Central
- 3Spam policies for Google web search: keyword stuffingGoogle Search Central
- 4Performance report (Search results)Search Console Help
- 5Performance report: advanced filtering and comparisonSearch Console Help
- 6A deep dive into Search Console performance data filtering and limitsGoogle Search Central Blog

CEO, Morrison
Ulrich is CEO of Morrison and founded Bonzer in 2017, growing it into one of Scandinavia's leading SEO agencies with 900+ clients across Copenhagen, Oslo, and Stockholm. At Morrison he leads strategy, operations and go-to-market, bringing years of hands-on SEO and content work to the platform side of the business.