All documentation

Engines and measurement

Which AI engines we measure, how we query them, and what a scan actually does.

The engines we measure

DiscoveredBy measures five engines: ChatGPT, Gemini, Perplexity, Claude and Grok. Every one of them is queried through its official API, never by scraping a browser session. In the platform's own bookkeeping this is recorded as the collection method, and all five engines share the same value: api. PROVIDER_PROVENANCE in api/services/collection.py stamps that value on every one of the five provider rows.

The word the platform uses to track an engine internally is not always the name of the company running it:

Engine you see Internal slug Company
ChatGPT openai OpenAI
Gemini gemini Google
Perplexity perplexity Perplexity
Claude anthropic Anthropic
Grok grok xAI

grok runs on xAI's infrastructure, and gemini runs on Google's: the slug names the API being called, not necessarily the brand a reader might expect from the word alone.

How an answer is labelled

Every prompt execution stamps its own copy of three fields the moment it runs: platform, surface and collection method (PromptExecution.platform, .surface and .collection_method in api/models/prompt_execution.py). These are copied from the provider catalogue at the moment the execution happens. They are not looked up live through the provider record afterward.

That is why an old answer keeps saying how it was actually collected. If the catalogue changes later, a provider renamed, a new surface added, a collection method swapped, none of that can reach back and relabel an execution that already ran: the row already carries its own copy of what happened, not a pointer to a catalogue entry that keeps moving underneath it.

Which engines run for your project

Which of the five engines actually run for your project comes from two things layered together: what your plan includes, and whether each engine is currently available to run at all.

Your project's plan lists which providers it includes (BillingPlan.providers, seeded from DEFAULT_PLANS in api/services/seed.py). Different plans include different subsets of the five engines. What each plan includes is covered on Pricing, not repeated here, so there is one place to keep it correct.

Being on your plan's list is not the same as running today. get_user_provider_ids in api/services/plan.py filters that list twice more: the provider row has to be marked active, and provider_is_available (in api/services/llm.py) has to return true for it, which in turn calls provider_has_api_key to check whether a key for that engine is currently configured on the platform. An engine can be missing from your project for a reason that has nothing to do with your plan: if its API key is not currently configured, that engine will not run for anyone, on any plan, until the key is back in place.

Fan-out

Some engines don't just answer a prompt directly. Internally, they can expand it into several related queries of their own, the way a person might turn one question into a few separate searches, before composing a final answer. DiscoveredBy captures that expansion where a provider exposes it, and shows it alongside the answer.

Fan-out is detail about a single execution, not a separate collected answer. However many queries a prompt expands into, it still counts as one completed execution for that engine on that day: query_executions carries a unique constraint on prompt target, provider and day (uq_qe_target_provider_date in api/models/prompt_execution.py). A prompt target is one prompt tracked in one country, so a prompt tracked in three countries produces three executions per engine per day, not one; fan-out does not change that count either way. Because the metrics on Metrics defined that divide by collected or analysed answers are built from this same execution count, a prompt that fans out widely does not, by itself, move one of those numbers differently from a prompt that does not fan out at all. See that page for which metric divides by which population.

Perplexity is the honest exception. DiscoveredBy calls Perplexity's search endpoint directly, rather than asking a general-purpose model that decides for itself whether and how to search, so there is no model-issued sub-query for Perplexity to report (SURFACES_WITHOUT_FAN_OUT in api/services/collection.py). An empty fan-out on a Perplexity answer means not applicable, not that the engine chose not to search: derive_fan_out_state in api/services/fan_out.py checks for this case first and returns not_applicable before anything else, specifically so a Perplexity run is never misread as an engine that answered without searching.

Where a provider does report sub-queries, DiscoveredBy also has a model read the captured ones, up to a limit on how many one run judges, and file each under a category describing its relationship to the parent prompt, stored in a table of its own rather than as a column on the query record, so a bad classification can never corrupt the record of what the engine actually searched for. See Fan-out for the category list, what happens to a query past that limit, how confident the model has to be before a label is shown, and what a run's fan-out looks like when little or nothing was captured for it.

  • Fan-out: the eight categories a captured sub-query can be classified into, and what each capture state means
  • Metrics defined: what collected and analysed answers mean, and why fan-out does not change either count
  • Pricing: what each plan includes
  • Troubleshooting: what to check when an engine looks inactive or a number looks wrong

Last verified 2026-08-08

Start monitoring your AI visibility.

See how AI search engines talk about your brand.

Free to start. No credit card required.