Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 3 min read

Your keyword report is probably double-counting. Here is how to fix it

If you have ever pasted a keyword list into a volume tool and summed the column, there is a good chance your total was wrong. It was not a little wrong, either. The problem: Google counts close variants once

If you have ever pasted a keyword list into a volume tool and summed the column, there is a good chance your total was wrong. It was not a little wrong, either.

The problem: Google counts close variants once

Google Ads Keyword Planner does not report a separate figure for every way of writing a phrase. Plurals, word order and small misspellings are grouped together, and the group gets one number.

Here is a real lookup we ran this week (United States, Google Search):

Keyword Searches / month
standing desk 135,000
standing desks 135,000
standing desk converter 18,100

Sum the column and you get 288,100. But "standing desk" and "standing desks" are the same 135,000 searches reported twice. The real total is 153,100. The naive sum overstates demand by 88%.

It gets worse with longer lists. Paste four variants of one phrase ("running shoes", "running shoe", "shoes running", "runing shoes") into a typical tool and one of two things happens:

  1. You get four rows of 246,000 that add up to 984,000 searches that do not exist, or
  2. Three of your keywords silently disappear from the output, and you never find out which ones.

Neither is acceptable if the number ends up in a client report, a market-size slide or a content plan.

Why tools do this

Keyword Planner returns one row per group, not per keyword you sent. A tool that maps the response back to your input has to choose: repeat the group figure on every variant (inflated totals) or drop the keywords that did not come back (missing rows). Most tools quietly pick one of the two and never tell you.

What we built

We built a small API on Apify that does the boring part properly:

  • One row for every keyword you sent. Nothing disappears.
  • Variants Google counts together share a variantGroup id.
  • countsTowardTotal is true for exactly one keyword per group. Sum only those rows and your total is right.
  • Every run stores a summary with both totalVolumeNaive and totalVolumeDeduplicated, so you can show the difference.

A variant group is only formed when the volume and all twelve monthly values are identical and the wording is close (plural, word order, a one- or two-letter difference). Unrelated keywords that happen to share a number are left apart.

Each row also has CPC, the top-of-page bid range, competition, the 12-month series, peak month and a seasonality index. You do not need a Google Ads account or an API key from Google.

Try it in one request

The Actor has an instant HTTP endpoint. Send keywords, get JSON back in the same response:

curl "https://countonce--keyword-search-volume-api.apify.actor/?keywords=standing%20desk,standing%20desks,standing%20desk%20converter&location=United%20States" \
  -H "Authorization: Bearer <APIFY_TOKEN>"

The response (shortened):

{
  "summary": { "requested": 3, "variantGroups": 1,
               "totalVolumeNaive": 288100, "totalVolumeDeduplicated": 153100 },
  "rows": [
    { "keyword": "standing desk",  "searchVolume": 135000, "cpc": 5.18,
      "variantGroup": "g1", "countsTowardTotal": true },
    { "keyword": "standing desks", "searchVolume": 135000, "cpc": 5.18,
      "variantGroup": "g1", "countsTowardTotal": false },
    { "keyword": "standing desk converter", "searchVolume": 18100, "cpc": 2.21,
      "variantGroup": null, "countsTowardTotal": true, "peakMonth": "December" }
  ]
}

For longer lists (up to 1,000 keywords), POST the same JSON you would use as the Actor input:

curl -X POST "https://countonce--keyword-search-volume-api.apify.actor/" \
  -H "Authorization: Bearer <APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"keywords": ["running shoes", "trail running shoes"], "location": "Germany", "language": "de"}'

It also works as a normal Apify run (paste keywords in the form, press Start), from n8n or Make with an HTTP Request node, and from AI agents through the Apify MCP server. If you hand the data to an LLM, tell it to sum searchVolume only where countsTowardTotal is true. Otherwise it will double-count, just like a spreadsheet would.

Pricing, plainly

  • $0.25 per live request (up to 1,000 keywords) + $0.0035 per keyword that has data.
  • 20 keywords cost $0.32, 200 cost $0.95, 1,000 cost $3.75.
  • Free: keywords with no data, invalid keywords, merged variants, and anything your account already fetched for the same market in the last 30 days.
  • You can set a maximum cost per run, and the Actor will not go over it.

The data is Google Ads Keyword Planner data, supplied by DataForSEO.

Takeaway

Even if you never use our tool, check your own keyword sheets for duplicated numbers. If two keywords show the same volume and the same 12-month curve, Google has counted them as one. Keep one row in the total, not both.

Actor: Google Ads Keyword Search Volume API on Apify

Disclosure: we built and maintain this Actor.

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.