GKP (Google Keyword Planner)¶
Code: kvprocessor.cpp — PullGKPData(). 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.2ceiling, so the blend can't blow up the monthly volume past 1.2× GKP. See memoryproject_gkp_cap_semanticsfor 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 thenull-for-prohibited behaviour we rely on for the GT cross-validation rule above.
Internal:
- Central hub table —
gkp_*columns extract_gkp.py— refresh extractor + DFSEO client- Decisions —
needs_gkpflag, GKP blend weights, 1.2× soft cap - Column-level reference — TBD:
../fields/