All documentation

Citation gaps

How a gap between you and a cited competitor is detected, ranked, and actioned.

Citation gaps list ranked by impact score, showing evidence for each opportunity and accept, dismiss, and open actions

What this is for

For every prompt you track, DiscoveredBy already knows which pages the AI engines are citing right now, whether that page is yours or a competitor's (see Citations). Citation gaps takes the prompts where a competitor is winning and you are not, and turns the difference into a ranked queue of specific changes: add this table, cover this figure, add this schema type, not a generic instruction to improve your content.

What a citation gap is

A citation gap is the difference between what the pages AI engines cite for a prompt contain and what your own page offers: the specific, missing piece keeping you out of the answer. Ask an engine "what's the best invoice software for a small agency?" and it synthesizes its answer from a handful of pages it trusts; if a competitor's page gets pulled in and yours does not, that is rarely random. The winning page usually has something concrete yours lacks: a comparison table, an FAQ answering the follow-up question, a statistic yours never states, a topic it covers that yours does not, cleaner structured data, a stronger outside source, or content that reads newer. DiscoveredBy checks a competitor's cited page against your best matching page for exactly these signals and records what it actually finds missing as evidence, not a guess (api/services/citation_gap.py#find_gaps_for_project). When no page of yours exists to compare at all, the opportunity is to create one rather than fix an existing page.

What you see

Citation gaps opens on the highest-impact opportunity still waiting on you: its impact score, the kind of fix, and why it was prioritized, linking into the detail page. Two smaller tiles count what is waiting on you and what you have shipped, which includes a fix that did not move your visibility, not only the ones that won.

Below that, a filterable table lists every opportunity: its impact score, the kind of fix, its status (new, accepted, implemented, monitoring, won, no lift, or dismissed), how much evidence backs it, your baseline visibility and the competitor citation count for that prompt cluster, and the actions available at that status: accept it, mark it done once you have made the change, dismiss it, or open the detail page. Accepting an opportunity (api/routers/citation_gaps.py#accept_citation_gap) also creates a candidate topic on the Articles screen, carrying this diagnosis with it so you do not re-type it (api/services/citation_gap.py#create_article_topic_from_opportunity). Nothing is written from that topic until you pick it there.

The detail page (api/routers/citation_gaps.py#get_citation_gap) repeats the impact score, status and confidence, and adds four tiles: prompts affected, your visibility, competitor citations, and estimated effort. Below that: the recommended actions, the evidence behind each (the claim, what your page does about it today, and a link to the source), the affected prompts, the competing URLs it was diagnosed against, and, once marked done, any visibility checks recorded afterward.

Refreshing on demand ("Refresh now") needs a plan that includes it; other plans see the same control link to billing instead (api/routers/citation_gaps.py#refresh_project_citation_gaps, frontend/src/routes/(app)/citation-gaps/+page.svelte#canRefresh). See Pricing for what each plan includes. New opportunities can also appear on their own from the weekly on-page optimization run, for plans that include it, without anyone pressing refresh.

How it works

A run starts from your tracked prompts. A prompt only becomes a candidate when two things are both true over the trailing window: you appear in under 30% of that prompt's own runs, and at least one citation in that window points at a domain that is not yours (api/services/citation_gap.py#_OWN_VISIBILITY_THRESHOLD, api/services/citation_gap.py#_MIN_COMPETITOR_CITATIONS). A prompt you already win most of the time never becomes a citation gap, even if a competitor is cited occasionally alongside you.

How many of those eligible prompts one run actually works through depends on how the run started. The weekly optimization run, the one with a deployed timer, works through as many as your plan allows (api/services/optimization/service.py#_optimization_limit); see Pricing for what each plan includes. The on-demand "Refresh now" button and the single-prompt refresh instead always work through at most 50, regardless of plan (api/services/citation_gap.py#_MAX_PROMPTS_PER_RUN). Either way, the prompts a run reaches first are the ones carrying the most competitor citations.

The prompts a run reaches are not a fixed queue, either. Each run re-reads which prompts are currently eligible and re-ranks them by competitor citations over the trailing window, so a prompt left out of one run is not guaranteed to be picked up by the next, and it is not permanently excluded either: whether a later run reaches it depends on how it ranks against that run's eligible prompts then, a different kind of bound from the fixed, capture-time order behind the cap on Fan-out.

For each candidate prompt, DiscoveredBy reads the five most-cited competing URLs for it (api/services/citation_gap.py#_TOP_URLS_PER_PROMPT) and looks for the page of yours most likely to compete: an explicit mapping if one has been set, otherwise a page of yours already cited for that prompt, otherwise your existing page with the closest keyword overlap to it. Below a minimum overlap, DiscoveredBy treats that as no match and recommends creating a new page instead of pointing at a weak one (api/services/citation_gap.py#_MIN_SIMILARITY); that threshold changes which fix gets recommended, not whether a gap is found at all. Pages not yet fetched are queued for the scrape worker and picked up again on a later run.

DiscoveredBy then compares your matched page, if one exists, against the competing pages for the signals described above; every difference found becomes one piece of evidence, and an opportunity with none is not created. Prompts resolving to the same page and fix type are merged into one opportunity, with its impact score reflecting the merged count. That score weighs the competitor's citation share for the cluster, how far under your visibility is, engine spread, evidence found, and how substantial the competing pages are (api/services/citation_gap.py#_impact_score).

The number of new opportunities a run actually saves is capped too, separately from the prompt-processing cap above. Clustering can turn up more distinct opportunities than a run keeps: they are sorted by impact score first, then cut down to a plan-derived limit, so anything dropped is always the lowest-impact opportunity found in that run, not an arbitrary one (api/services/citation_gap.py#_limit_for_plan, api/services/citation_gap.py#_PLAN_LIMITS). This is the number of new opportunities that actually show up in your queue after a run, so it is the bound you feel more directly than the processing cap above; see Pricing for what each plan includes.

Citation gap opportunities are generated only on plans that include the feature; see Pricing for what each plan includes. Marking an opportunity done sets its status to implemented, not monitoring (api/routers/citation_gaps.py#mark_citation_gap_implemented). From there it can advance to won, no lift, or monitoring, but only once something checks your visibility for its prompt cluster again, at the 7, 14, and 30 day mark after you marked it done: won if visibility has risen at least 10 points from its baseline or reads 20% or higher on its own, no lift if neither is true by the 30-day mark, monitoring if neither is true yet and the 30-day mark has not arrived (api/services/citation_gap.py#refresh_outcomes_for_project). Two jobs call that check, and neither of them is this screen's own "Refresh now": pressing Refresh here regenerates opportunities, it does not check outcomes on ones already marked implemented. The older caller is the project's topic-generation job (api/tasks.py#_run_generate_topics_for_project). The newer one exists only to run the check, and it fans out to a project only when four things are true at once: the project holds an opportunity whose status is implemented or monitoring, that opportunity carries the date you marked it done, the project is active, and the account it belongs to is active. A project with nothing left to re-read is skipped rather than queued (api/services/citation_gap.py#project_ids_with_pending_outcomes, api/tasks.py#_enqueue_citation_gap_outcomes_for_eligible_projects, api/cli.py#cmd_enqueue_citation_gap_outcomes). That second job and the daily schedule written for it, discoveredby-cli@enqueue-citation-gap-outcomes.timer, were added to the codebase in the same change; a schedule only starts firing once a deployment installs it.

Publishing an article linked to the opportunity is a separate way into monitoring: it moves the opportunity straight there on its own, independent of either job (api/services/articles.py#_attach_publication_monitoring). Until one of those three things happens for your project, an opportunity stays where you left it.

What the numbers mean

Impact score, out of 100, ranks opportunities against each other for this project; read it as a relative order, not a percentage of anything. Confidence (low, medium, high) reflects how much evidence was found and whether a specific page could be matched to the prompt, not how sure DiscoveredBy is the fix will work. Effort (low, medium, high) is a fixed estimate per fix type, not a measurement of your specific page. The prompts affected, your visibility, and competitor citations tiles are baseline measurements for the affected prompt cluster over the window the opportunity was found in, not a live number that moves as you read it. For how to read a change against a baseline in general, see How to read any number here.

Last verified 2026-08-11

Start monitoring your AI visibility.

See how AI search engines talk about your brand.

Free to start. No credit card required.