---
title: Check SEO and GEO visibility for a keyword
description: Check where a domain ranks in Google, whether AI answers (Google AI Mode, Google AI Overview, ChatGPT) mention or cite it, search volume, and backlink strength.
---

GEO here means generative engine optimization: whether an AI answer mentions or cites your domain,
next to the classic SEO question of where you rank in search results. This walks through five jobs
that together answer both.

## What it costs

`google.serp.organic` and `google.keywords.volume` and the AI-answer jobs each price differently,
and `google.keywords.volume` in particular is priced much higher than a results page. Quote each
one before you run it:

```json MCP
search {"filters": {"capability": "google.serp.organic"}, "prefer": "cheapest"}
```

On 2026-09-28 the cheapest listed prices were `google.serp.organic` around $0.0019 per call,
`google.serp.ai-mode` around $0.002 per call, `google.keywords.volume` around $0.09 per call, and
`backlinks.domain.summary` around $0.024 per call on its one provider. Read the live numbers and
check [`balance`](/mcp-tools/balance) before running the whole set on a list of keywords.

1. **Google results**

    `google.serp.organic` takes `query`, and optionally `location`, `language`, `country` and `device`:

    <CodeGroup>

    ```json MCP
    run {"endpointId": "job:google.serp.organic", "input": {"query": "best crm for startups", "location": "United States"}, "idempotencyKey": "geo-crm-organic", "fallback": true}
    ```

    ```bash REST
    curl -s "https://api.looot.ai/v1/runs?wait=20" \
      -H "Authorization: Bearer $LOOOT_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "endpointId": "job:google.serp.organic",
        "input": {"query": "best crm for startups", "location": "United States"},
        "idempotencyKey": "geo-crm-organic",
        "fallback": true
      }'
    ```

    ```bash CLI
    looot run job:google.serp.organic \
      --input '{"query": "best crm for startups", "location": "United States"}' \
      --wait
    ```

    </CodeGroup>

    Read `result` for the ranked list and find your domain's position, if it appears at all.

2. **AI answers: AI Mode, AI Overview, ChatGPT**

    These three, `google.serp.ai-mode`, `search.google-ai-overview` and `search.chatgpt`, are each
    served by one provider today, so search for the job, inspect the endpoint it returns, and send that
    endpoint's own required fields. Don't guess a shared input name:

    ```json MCP
    search {"filters": {"capability": "search.chatgpt"}}
    ```

    ```json MCP
    inspect {"endpointId": "<endpointId from that search>", "detail": "run"}
    ```

    [`inspect`](/mcp-tools/inspect) returns `requiredInputFields`, `inputSchema` and a [`run`](/mcp-tools/run) template with the exact field
    names that endpoint takes. Fill in the placeholders and run it with your own [`idempotencyKey`](/concepts/idempotency).
    Repeat for `google.serp.ai-mode` and `search.google-ai-overview`.

    Read each answer's text from `result` and check whether it names or links your brand and domain.

3. **Search volume for the keyword**

    `google.keywords.volume` is priced higher than a results page, so quote it first (step above). It
    takes a `keywords` array:

    <CodeGroup>

    ```json MCP
    run {"endpointId": "job:google.keywords.volume", "input": {"keywords": ["best crm for startups"], "location_name": "United States"}, "idempotencyKey": "geo-crm-volume", "fallback": true}
    ```

    ```bash REST
    curl -s "https://api.looot.ai/v1/runs?wait=20" \
      -H "Authorization: Bearer $LOOOT_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "endpointId": "job:google.keywords.volume",
        "input": {"keywords": ["best crm for startups"], "location_name": "United States"},
        "idempotencyKey": "geo-crm-volume",
        "fallback": true
      }'
    ```

    ```bash CLI
    looot run job:google.keywords.volume \
      --input '{"keywords": ["best crm for startups"], "location_name": "United States"}' \
      --wait
    ```

    </CodeGroup>

4. **Domain strength**

    `backlinks.domain.summary` takes `domain` and gives back authority and backlink totals:

    ```json MCP
    run {"endpointId": "job:backlinks.domain.summary", "input": {"domain": "example.com"}, "idempotencyKey": "geo-example-backlinks", "fallback": true}
    ```

    Read `normalized.fields.backlinks`, `.referringDomains` and `.rank` when [`normalized`](/concepts/normalized-output) is present,
    or `result` otherwise.

5. **Report**

    Say where the domain sits in the organic results, whether each AI answer mentions or cites it and
    what it says, the keyword's search volume, and the domain's backlink totals. Name the provider
    behind each fact ([`servedProviderId`](/concepts/served-provider)) and the total spent (`actualCost` summed across runs).

:::note
looot 1.1.0 does not accept `--fallback` on `looot run`. Use MCP or REST when you want a job to try
more than one provider.
:::

:::tip
Before a job you have not run yet, [`search`](/mcp-tools/search) its job id and read [`jobInputs`](/concepts/job-inputs): the live input names
there win over anything shown here.
:::

## What the answer looks like

| Field | What it is |
| --- | --- |
| `status` | `completed`, `failed`, `queued`, `running` |
| [`outcome`](/concepts/outcomes) | `hit`, `weak`, `miss`, `error`, `rejected`, `skipped` or `pending` |
| `servedProviderId` | the provider that answered |
| `actualCost` | what this run charged |
| `normalized.fields` | only on `backlinks.domain.summary`: `backlinks`, `referringDomains`, `rank` |
| `route.summary` | fallback runs only |

The organic, AI-answer and keyword-volume jobs have no `normalized` map yet: read `result` and
check the field names the provider used, or use `inspect` on the endpoint first to see its
`outputSchema`.

## On a miss or error

- An AI answer job with one provider and no [`fallback`](/concepts/fallback): a miss there is a plain `outcome: "miss"`,
  with nothing else to try. Retry later or note the gap in the report.
- [`no_supply_for_job`](/errors/job-refusals#no_supply_for_job): no endpoint currently does that job. [`capability_request`](/mcp-tools/capability-request) asks looot to add
  one.
- [`insufficient_balance`](/errors/rest-errors#insufficient_balance): the run is blocked and not charged. Use [`top_up`](/mcp-tools/top-up), then retry with a new
  `idempotencyKey`.

<Related />
