Skip to content

GKP (Google Keyword Planner)

Code: kvprocessor.cppPullGKPData(). src/extract_gkp.py for extraction via DataForSEO. Primary validity: processing.py:KB-ANCHOR:gkp-validity-with-js-fallback. Last validated: 2026-05-21

What it carries

Per-keyword monthly absolute search volume (raw UInt32 — not normalised 0–100 like GT), plus monetisation signal: low / high top-of-page bids and CPC. The absolute scale is what makes GKP load-bearing: it anchors the volume blend when GT (which is only relative) and GSC (which is impression-not-volume) need a reference magnitude.

Where it lives and how it gets here

src/extract_gkp.py calls DataForSEO's Google Ads Search Volume Live endpoint, throttled to ~10 req/min (the published hard cap is 12 req/min — we leave headroom). Results land in keywords_volume.gkp_trends_raw on isog. kvprocessor.cpp pulls into the hub on each run.

Like GT, refresh priority is signal-driven via needs_gkp in processed_volume_trend_meta.

Validity gates in processing.py

Primary gate (KB-ANCHOR:gkp-validity-with-js-fallback):

with_gkp_data = (sum(gkp_trend_array) > 0) or (
    (len(gkp_trend_array) > 0) and (len(js_predicted_volumes) == 0)
)

That is: GKP is "valid" if either (a) it has any positive volume, or (b) it's present-but-all-zero and there's no JS data to contradict. The all-zero-when-no-JS case is intentional — it's our way of saying "we explicitly checked DataForSEO and confirmed near-zero, with no stale-baseline source disagreeing".

Secondary exclusion (KB-ANCHOR:gt-gsc-correlation-gate): if GT exists and GT is correlated with GSC (via are_trends_close, default threshold 0.7), and GKP is all-zero with no JS, with_gkp_data is forced false — three corroborating signals (GT, GSC correlation, JS absence) override the "we explicitly checked" interpretation.

Important caveat: prohibited keywords

DataForSEO's Google Ads Search Volume endpoint will return null / zero for keywords that Google Ads refuses to surface — most notably:

  • Adult content keywords (Google Ads policy restriction).
  • Keywords containing restricted symbols / characters (UTF symbols, emojis, etc.).

For these keywords, all-zero GKP does not mean "low search volume" — it means "we are prohibited from learning about this keyword via the Ads API". Cross-validate using GT: if GT shows activity, the keyword is real and the GKP zeros are a restriction artifact, not a true zero. See the Google Ads Search Volume docs § Restrictions for the full restriction list.

GKP's dual role (blend + soft cap)

GKP is unusual in feeding two parts of the pipeline:

  • Blending — its absolute monthly values anchor the volume scale during trend merge.
  • Per-month soft cap — a single filled GKP series (direct → GT-inferred → interp + GSC) is also applied as a × 1.2 ceiling, so the blend can't blow up the monthly volume past 1.2× GKP. See memory project_gkp_cap_semantics for the cap semantics.

See also

Reference docs (external):

  • DataForSEO Google Ads — Search Volume Live — the exact endpoint we call. POST /v3/keywords_data/google_ads/search_volume/live. Documents: returned fields (monthly average volume, competition, CPC, low/high top-of-page bids, past-24-month trends), keyword restrictions (adult content, restricted symbols), and the null-for-prohibited behaviour we rely on for the GT cross-validation rule above.

Internal: