{
  "slug": "unique-keywords",
  "name": "Unique keywords",
  "aliases": [
    "Total keywords",
    "Unique keyword count"
  ],
  "definition": "How many distinct keywords produced at least one impression for the site in the period.",
  "category": "Search performance",
  "type": "raw measure",
  "unit": "distinct keywords",
  "direction": "higher-better",
  "verification": "verified",
  "calculation": "`NULLIF(COUNT(DISTINCT keyword), 0)` on the keyword-and-page combined table.",
  "aggregation": "A distinct count. It never sums, two periods' counts do not add, and the counts of two slices do not add to the count of their union.",
  "grain": "One date range × the whole site.",
  "dimensions": [
    "brand",
    "intent",
    "search type"
  ],
  "requiredFilters": [
    "date range"
  ],
  "sources": [
    "search-console"
  ],
  "reports": [
    "cannibalization-report",
    "content-performance-report",
    "keyword-ranking-report",
    "weekly-search-report"
  ],
  "skills": [
    "weekly-search-report",
    "monthly-exec-review",
    "quattr-iq"
  ],
  "verbs": [
    "search_performance"
  ],
  "rungs": [
    "R2"
  ],
  "levers": [
    "L2",
    "L5"
  ],
  "questions": [
    "How many unique keywords do we rank for?",
    "How many non-brand keywords did we appear for last month?"
  ],
  "interpretation": "Coverage of the demand pool rather than performance within it, the breadth half of the Retrieved rung. It moves with content footprint and with seasonality of the long tail, so a rise is a coverage signal and not a traffic signal.",
  "caveats": [
    "Only the keyword-and-page combined table serves this correctly. The keyword-only rollup reads a larger keyword universe and over-counts to the point where a non-brand slice exceeded the all-searches total on two live tenants, which is impossible for a subset, so branded and intent slices are deliberately routed to the keyword-and-page table.",
    "It cannot be requested in the same query as clicks, impressions, CTR or position: the count metrics live on a different dataset and the query assembler refuses the mix rather than returning a wrong field.",
    "Privacy-suppressed queries are not counted, so this is distinct keywords that were reported, not distinct keywords that existed."
  ],
  "freshness": "1 to 2 days behind, Google's own reporting lag. Any answer touching the last 48 hours says so on the card.",
  "failureModes": [
    "Summing the count across weeks to produce a quarter.",
    "Comparing a branded and a non-branded count and expecting them to add to the total."
  ],
  "notSameAs": [],
  "related": [
    "unique-pages",
    "impressions",
    "keyword-page-click-coverage"
  ],
  "workflows": [],
  "lastVerified": "2026-08-04"
}