CitationBenchTalk to Sales
Concepts

2D Keyword Labelling: intent and relevance, scored with confidence

Every keyword carries two labels — intent and relevance — plus confidence scores, replacing coarse single-axis intent tagging with the labels that actually drive content decisions.

CitationBench's most distinctive data model. Every keyword carries two labels — intent and relevance — and confidence scores on both. The labels drive nearly every downstream decision: which keywords get landing pages, which get blog posts, which get pursued for link building, which get archived.

For the underlying keyword resource (status, source, priority, lifecycle), see Keywords. This page is just the labeling system.

The short version

Every labeled keyword has:

  • Intent — what the searcher is trying to do (URGENCY, PURCHASE, LOCATION, SPECIFICATION, PRODUCT, PROBLEM_SOLUTION, ALTERNATIVE)
  • Relevance — how the keyword relates to your business (OFFERING, ALTERNATIVE, COMPLEMENTARY, INCUMBENT)
  • Confidence scores on both axes
  • A labelReason explaining the labeler's call
{
  "keyword": "best alternative to monday.com",
  "intentLabels": ["ALTERNATIVE"],
  "intentConfidence": 0.94,
  "relevanceLabel": "ALTERNATIVE",
  "relevanceConfidence": 0.91,
  "isHighIntent": true,
  "isHighRelevance": true,
  "labelReason": "Searcher actively shopping for a substitute for an incumbent we compete with."
}

Why two axes

Most SEO tools tag intent on a single axis — typically informational / commercial / transactional. That's useful but coarse. It can't distinguish:

  • "how to use monday.com for engineering teams" (someone using your competitor)
  • "best alternative to monday.com" (someone shopping away from your competitor)
  • "project management for engineering teams" (someone shopping in your category)

All three are "commercial." They demand completely different content.

CitationBench splits the problem:

  • Intent answers what's the searcher doing in their journey?
  • Relevance answers what's this keyword's relationship to your business?

Two axes. Cleaner segmentation. Better targeting.

The intent axis

The seven intents.

IntentMeaningExample
URGENCYThe searcher needs an answer now"fix gsc 503 error"
PURCHASEThe searcher is ready to buy"buy project management software"
LOCATIONThe searcher needs a place"project management agency london"
SPECIFICATIONThe searcher is comparing features"project management tool with timeline view"
PRODUCTThe searcher wants a product overview"monday.com pricing"
PROBLEM_SOLUTIONThe searcher has a problem and wants the solution"how to track team capacity"
ALTERNATIVEThe searcher wants an alternative to something"alternatives to asana"

A keyword can carry multiple intent labels when the query is ambiguous — intentLabels is an array. intentConfidence is the agent's confidence in the primary label.

The relevance axis

The four relevances.

RelevanceMeaningExample for a PM tool company
OFFERINGThe keyword is for your category"project management software"
ALTERNATIVEThe keyword is about leaving a competitor"asana alternatives"
COMPLEMENTARYThe keyword is for an adjacent need"time tracking for teams"
INCUMBENTThe keyword is for the dominant competitor"monday.com tutorial"

Unlike intent, relevance is single-valued — the agent picks one.

How CitationBench assigns labels

The agent infers both axes automatically.

  1. At discovery. When you call research.keyword, every discovered keyword goes through a labeling pass — an LLM with strict JSON-Schema output, given your workspace's product description and ICP as context.
  2. In bulk. Re-label your full library at any time via POST /v1/keywords/relabel. Useful after refining your product description.
  3. Manually. Override either label from the dashboard or via PATCH /v1/keywords/{id}.

Confidence is exposed on both axes (intentConfidence, relevanceConfidence). CitationBench will flag low-confidence labels for review (the isHighIntent / isHighRelevance booleans roll up the confidence thresholds).

Why this matters downstream

The 2D label drives nearly every downstream tool's defaults.

  • produce.landing_page defaults to keywords with intent ∈ {PURCHASE, SPECIFICATION, PRODUCT} and relevance = OFFERING
  • produce.blog_post defaults to intent ∈ {PROBLEM_SOLUTION, SPECIFICATION} across all relevances
  • link_building.serp_outreach defaults to relevance = COMPLEMENTARY (those are the partners worth talking to)
  • The refresh_stale skill checks rank drops on intent = PURCHASE first (highest-value)
  • The rank_monitor skill weights alerts by intent × relevance to surface the consequential drops first

If you don't override, the platform makes sensible choices.

Querying by label

# Every keyword where someone is comparing us to an incumbent
curl -X POST https://api.citationbench.com/v1/keywords/search \
  -H "Authorization: Bearer sk_live_***" \
  -d '{
    "intent": ["ALTERNATIVE"],
    "relevance": ["INCUMBENT", "ALTERNATIVE"],
    "minConfidence": 0.8
  }'
# Every PROBLEM_SOLUTION keyword in pillar "performance"
curl -X POST https://api.citationbench.com/v1/keywords/search \
  -d '{
    "pillarId": "pil_***",
    "intent":   ["PROBLEM_SOLUTION"]
  }'

In MCP, the same query through natural language:

Show me every keyword where people are comparing us to monday.com — high confidence only.

Claude calls research.keyword.search with the right filters.

Common patterns

1. The standard segmentation matrix

A useful exercise after bootstrap_brand: run all 7 × 4 = 28 cells and see where your keyword distribution lives. Usually two or three cells dominate. Those are the cells to write content for.

for INTENT in URGENCY PURCHASE LOCATION SPECIFICATION PRODUCT PROBLEM_SOLUTION ALTERNATIVE; do
  for RELEVANCE in OFFERING ALTERNATIVE COMPLEMENTARY INCUMBENT; do
    COUNT=$(curl -sf -X POST .../v1/keywords/search \
      -d "{\"intent\":[\"$INTENT\"],\"relevance\":[\"$RELEVANCE\"]}" | jq '.total')
    echo "$INTENT × $RELEVANCE: $COUNT"
  done
done

2. Relabel after a product change

Edit your workspace's product description, then:

curl -X POST .../v1/keywords/relabel -d '{ "scope": { "status": "LABELED" } }'

The agent re-runs the labeling pass with the new context.

3. Use ALTERNATIVE × INCUMBENT to find win-back content

Searchers using these queries are actively considering leaving your competitor. Drop in a landing page with a direct comparison and a CTA.

4. Use COMPLEMENTARY × PROBLEM_SOLUTION for top-of-funnel content

Searchers with a related problem but who haven't framed it as "your category yet." Great for ungated blog content + nurture sequences.

On this page