Methodology

The Visibility Method

One check, sixteen measures, one total. The method reads the public page, asks four prompts, and adds the points. The ten page measures and the six answer measures are steps of that check. They are not two scores placed side by side.

The total is out of 100 when both steps return. When the ask step is not scored, the total is the ten page measures, out of 55. A missing sample is not stored as zero. ChatGPT, Perplexity, Gemini, and Google AI reweight the page measures only. They are not the ask step.

01

The Visibility Method

The method answers one question: can this page be fetched and quoted, and does a live answer name the campaign, place it, cite it, and describe it in a way that matches the page? A fetchable page that is described wrongly is not a strong result. A flattering answer that the page cannot support is not a strong result either. Both kinds of evidence stay in the same total, and each measure stays on its own line.

  1. Read. Fetch the submitted URL, robots.txt, llms.txt, and sitemap.xml. Score ten page measures. Their maxima are 7, 8, 4, 6, 8, 12, 4, 2, 1, and 3. They sum to 55.
  2. Ask. Send four prompts to one engine, Grok, with web search. The prompts use the campaign name, type, city, and state. Score six answer measures: mention rate 9, answer position 6, share of voice 6, citation sources 12, description accuracy 8, and sentiment 4. They sum to 45. A high mention rate does not cancel an inaccurate description or a negative tone.
  3. Add. When the ask step scores at least one measure, add the two integers. The result is out of 100. When the ask step is not scored, publish the page measures only, out of 55. Do not fill the missing 45 points with zero.

The four platform numbers are a reweight of the read step. They are not a fourth step, and they do not query those products. The rules for each measure are below. This page is the spec for the free check. It is not the managed Election GEO assessment. A higher total means more of this evidence was present. It is not a forecast of traffic, donations, or votes.

02

What the check fetches

The read step requests four public addresses:

  • The submitted URL, followed through up to four redirects. The score uses the final URL.
  • /robots.txt on the final origin.
  • /llms.txt on the final origin.
  • /sitemap.xml on the final origin. A missing robots, llms, or sitemap file does not fail the scan.

The request uses the user agent OdysseyCampaignsVisibilityScan/1.0 and a link back to this site’s check page. Each page request waits up to 12 seconds and accepts a body of up to 1.5 MB.

The ask step is the same run, not a second product. When an engine key is configured, it sends the four prompts to the xAI Responses API with web search, two at a time. Each prompt waits up to 80 seconds. If the key is missing, or every prompt fails, the method still returns the read step and says the answer measures were not scored. A prompt that returns no text is named in the result and is left out of the ratios. Its points are not given to the signals that did return.

Only http and https URLs are accepted. The host must resolve to a public address. If the local resolver fails, or returns a private address, the check asks Cloudflare DNS for a public A record and connects to that address with the original host name. Local hosts, private addresses, and URLs with a username or password are refused. A page over 1.5 MB, more than four redirects, a non-HTML document that returns HTTP 200, or a timeout ends the scan with an error instead of a low score.

The scan route allows eight checks per IP address in a rolling minute. The limit is kept in memory on that server instance.

03

How points are assigned

Each measure produces a ratio from 0 to 1. The ratio is multiplied by that measure’s maximum. The ten page measures are turned into one integer inside 55 points. The six answer measures are turned into one integer inside 45 points. The method adds those two integers. It does not throw all sixteen lines into one rounding pool. The page maxima are 7, 8, 4, 6, 8, 12, 4, 2, 1, and 3. The answer maxima are 9, 6, 6, 12, 8, and 4.

Inside each step, the displayed points are integers and they sum to that step’s integer:

  1. Add the raw products in that step.
  2. Round that sum to the nearest integer and keep it inside the step’s cap, 55 or 45.
  3. Start each measure at the whole-number part of its own product.
  4. Give the remaining points, one at a time, to the measures with the largest fractional parts.

A measure can show fewer points than a simple rounding of its own product when another measure in the same step had a larger fraction. If an answer measure cannot be scored because the answers do not support it, it is left out and the remaining answer weights are scaled to 45. A measured zero stays. If a prompt returns no text, the measures that were scored keep their own maxima and those missing points are not reassigned. If no answer measure can be scored, the method total is the page integer, out of 55.

04

The ten checks

These ten measures are the read step. The points under each name are that measure’s maximum inside the 55 page points. Platform columns use a different set of weights, listed after these rules. The ratio rules stay the same.

Crawl access

7 points

Whether robots.txt allows the retrieval crawlers that fetch pages for answers, on the final URL path.

  • If /robots.txt returns HTTP 200, the ratio is the average of four allow-shares: ChatGPT retrieval, PerplexityBot, Googlebot, and Bingbot.
  • ChatGPT’s share is the share of OAI-SearchBot and ChatGPT-User that are allowed, so it is 0, 0.5, or 1. PerplexityBot, Googlebot, and Bingbot are each 0 or 1. Gemini uses the Googlebot share. Googlebot is counted once in the total.
  • GPTBot, ClaudeBot, and Google-Extended are training crawlers. The finding names them when they are blocked. Blocking them does not lower the score.
  • If robots.txt is missing or does not return HTTP 200, the total uses 0.75. The finding says retrieval crawlers are allowed by default and that a named file is clearer.
  • The parser groups User-agent lines, strips comments, and uses the named agent group when one exists. Otherwise it uses the * group. The longest matching path prefix wins. An empty Disallow is ignored. Allow is applied after Disallow in the same group, so an equal-length Allow wins over that Disallow. This is a prefix match. It does not implement wildcards or end anchors from the full robots.txt specification.

Indexable page

8 points

Whether the URL returns readable HTML and is not marked noindex. The title is not part of this check.

  • HTTP 200 adds 0.4.
  • At least 300 visible words add 0.4. At least 120 and fewer than 300 add 0.2.
  • A page that is not marked noindex adds 0.2. noindex is read from the robots meta tag or the X-Robots-Tag header.
  • A noindex page also caps this ratio at 0.2. The cap only lowers the score. It does not grant points by itself.
  • Visible text drops script, style, and noscript blocks before the word count.

Title and description

4 points

A specific title and a meta description an answer could quote.

  • The title is the visible text of the title element, up to 180 characters.
  • A title that is exactly Home, Welcome, Untitled, or Index receives no title credit. Any other non-empty title does.
  • A specific title of 20–70 characters adds 0.5. A shorter specific title of at least 12 characters adds 0.3. Any other specific title adds 0.15.
  • A meta description of 50–170 characters adds 0.5. One of at least 30 characters adds 0.25. Any shorter description adds 0.1.

Service and place

6 points

The page says what is offered and where the work happens. Service is 0.55. Place is 0.45.

  • Service credit matches a fixed word list, or a JSON-LD type containing Legal, LocalBusiness, ProfessionalService, Attorney, Organization, Physician, or Dentist.
  • The word list is lawyer, attorney, law firm, law office, esq, legal services, practice, clinic, dentist, physician, plumber, restaurant, salon, agency, consultant, candidate, campaign, senator, senate, election, ballot, voter, software, beauty, spa, and messaging.
  • Place credit matches a U.S. state name or District of Columbia in the examined text, the phrases serving, located in, office in, or near, a City, ST pattern in the title, H1, or schema text, or addressLocality, streetAddress, or postalCode in the HTML.
  • The examined text is the title, the H1, the first 4,000 characters of visible text, and schema name, address, and telephone fields.

Answer-first sections

8 points

H2 or H3 headings followed by a short block of text. Full credit needs two ideal answers.

  • Only H2 and H3 headings count. The text under a heading runs until the next H2 or H3.
  • The word count uses the visible text of that block, and only the first 1,200 characters of that visible text.
  • An ideal answer is 40–70 words. A near answer is 20–110 words and is not already ideal. A near answer counts as half.
  • The ratio is the smaller of 1 and (ideal count + near count × 0.5) / 2. Two ideal headings reach 1. Extra headings do not raise it further.
  • A heading does not have to be phrased as a question.

Structured data

12 points

JSON-LD that identifies the organization, links a public entity profile, and matches a visible FAQ.

  • The check reads script blocks of type application/ld+json, including objects inside @graph. A block that is not valid JSON is skipped.
  • Any JSON-LD scores 0.25. A strong type scores 0.55 instead. No JSON-LD scores 0.
  • A link to Wikipedia, Wikidata, LinkedIn, X, Twitter, Facebook, Instagram, YouTube, or Crunchbase, in sameAs or in an href on the page, adds 0.25.
  • FAQPage whose question names appear in the visible text adds 0.20. FAQPage markup that the visible text does not match adds 0.05. The ratio stops at 1.
  • Strong types are LegalService, Attorney, Lawyer, LocalBusiness, ProfessionalService, Organization, Person, Physician, and Dentist.

Contact record

4 points

A name, a street address, and a phone number on the page. Name is 0.25, street is 0.4, and phone is 0.35.

  • Name credit uses a JSON-LD name, og:site_name, or the H1.
  • Street credit uses a JSON-LD address that includes streetAddress or addressLocality, or a street-like line in the visible text. That line needs a number and a suffix such as Street, Avenue, Road, Boulevard, Drive, Lane, Way, Court, or Suite, including common abbreviations.
  • Phone credit uses a telephone field in JSON-LD, or a U.S.-style number with separators in the visible text or schema text.

Contact path

2 points

A next step on the page. The ratio is capped at 1.

  • A tel: link adds 0.45.
  • A link whose address contains contact, consult, appointment, schedule, or intake adds 0.55. A form adds the same 0.55. Those two do not stack with each other.
  • If there is no contact link and no form, the phrases contact us, call now, free consultation, schedule a, request a consult, or speak with an attorney add 0.3.

Discovery files

1 points

A plain-text /llms.txt file and an XML sitemap at the site origin. The file is 0.60. The sitemap is 0.40.

  • llms.txt scores 0.60 when it returns HTTP 200, is not an HTML page, and has at least 120 characters. The same conditions with at least 40 characters score 0.25.
  • The file is treated as HTML when the first 300 characters contain a doctype or an html tag. An HTML file, a short file, a missing file, or a non-200 response scores 0 for this part.
  • /sitemap.xml scores 0.40 when it returns HTTP 200 and the body contains a urlset or sitemapindex element and at least one loc element.
  • The two parts add together and stop at 1. The check reads the sitemap file. It does not fetch the URLs listed in it.

Freshness

3 points

A date the check can parse, then the age of that date. A copyright year is the fallback.

  • The first usable date wins, in this order: JSON-LD dateModified or article:modified_time, the Last-Modified header, then JSON-LD datePublished.
  • A future date scores 0.7. A date within 540 days scores 1. A date within 1,080 days scores 0.65. An older date scores 0.3.
  • If no date parses, a copyright year equal to the current UTC year or the previous year scores 0.35. Otherwise this check scores 0.

05

Platform scores

Each platform column runs the same rounding method on the read step, with its own weights. The weights in a column sum to 55. They are a published emphasis for that column, not a measurement from that product, and they are not the six answer measures.

Crawl access is the one exception. A platform score uses that platform’s own allow-share, not the averaged crawl ratio used in the total. If robots.txt is missing, each platform allow-share stays at 1, so the platform crawl line is full credit, while the total crawl line uses 0.75.

Points available in the total and in each platform score
CheckTotalChatGPTPerplexityGeminiGoogle AI
Crawl access79464
Indexable page869711
Title and description43434
Service and place63444
Answer-first sections81012911
Structured data1211101510
Contact record43344
Contact path22233
Discovery files11111
Freshness37633
Sum5555555555
Crawlers named in the crawl check
Platform columnCrawlers
ChatGPTOAI-SearchBot and ChatGPT-User
PerplexityPerplexityBot
GeminiGooglebot
Google AIGooglebot

If a named crawler is blocked, that platform’s note names it. If every named crawler for that platform is allowed, the note names the check with the lowest ratio for that platform. The crawl ratio in that comparison is the platform’s own allow-share.

The column emphasis is visible in the table. ChatGPT’s column gives the most weight to structured data, then answer-first sections. Perplexity’s column gives the most weight to answer-first sections, then structured data. Gemini’s column gives the most weight to structured data. Google AI’s column gives the same weight to an indexable page and to answer-first sections. Discovery files are 1 point in every column. In the October 14 comparison, a present llms.txt did not separate high and low GEO scores, and the sites with a Wikipedia entity did.

Points available in the six answer measures
SignalPoints
Mention rate9
Answer position6
Share of voice6
Citation sources12
Description accuracy8
Sentiment4
Sum45

Citation sources have the most answer points because the open GeoScore GEO number moved with citations and entity evidence, not with llms.txt. Description accuracy is next so a wrong description can lower the one total even when the brand is named often. Sentiment is its own measure, smaller than accuracy, because tone is not the same thing as a true description. If a measure cannot be scored because the answers do not support it, it is left out and the remaining answer weights are scaled to 45. A measured zero stays in. A prompt that returns no text does not move its points onto the other measures.

06

How to read a result

The large number is the Visibility Method total. It is out of 100 when the ask step is scored: the page integer plus the answer integer. It is out of 55 when the ask step is not scored, so a missing sample is not stored as a zero. Under it, each of the sixteen measures shows its own points. The six answer measures stay separate so a high mention rate can sit next to a wrong description or a negative tone.

The four platform numbers are the read step, reweighted, out of 55. They can sit away from each other because their weights differ and because a blocked crawler changes only that platform’s crawl line. They are not four answer audits.

Use a low line as a fix list for the page that was scanned: publish the missing file, add the missing heading and answer, add JSON-LD, or put the name, street, and phone on the page. The finding sentence is the check’s own description of that URL. It is not a recommendation generated by a model.

07

Comparison with other checkers

On October 14, 2026 the same ten homepages were scored with this check and with the open-source GeoScore audit at geoscoreapp.pages.dev. GeoScore splits a technical SEO score from a GEO score. This check’s old total tracked the SEO number. The GEO number stayed much lower on the campaign and product sites.

None of the ten robots.txt files blocked an AI crawler, so crawler access did not explain the gap. llms.txt was already present on several sites whose GEO score was still under 30, including sites that scored below a site with no llms.txt. Stripe, the one site with a Wikipedia article, was the high GEO score. The repeated GeoScore findings on the other nine were no Wikipedia page, no Wikidata entity, and no social profile on the homepage.

That comparison is why this is one method. The old total tracked GeoScore’s SEO column and left the GEO gap unpublished. In that GeoScore audit the overall figure mixed its SEO score at about 55 percent with its GEO score at about 45 percent. The method keeps both: 55 points on the read step and 45 on the ask step, added into one total. Inside the read step, discovery files are 1 point and structured data is 12, because llms.txt did not separate the GEO column and an entity link did. Citation sources take 12 of the 45 ask-step points for the same reason. Sentiment is 4 points of its own, not a footnote on accuracy.

Homepage scores on October 14, 2026, before this rules change
SiteThis checkGeoScore SEOGeoScore GEO
larryhe.com706814
whyivote.ai828419
odysseycampaigns.com828921
360aimedia.comnot scored7025
gobeauty.ai848224
freemessaging.ai828827
eatadvisor.ai58378
360ailegal.com627616
campaignairesearch.com557619
stripe.com878952

360aimedia.com did not resolve on the office DNS resolver in that run, so the old check produced no score. The resolver fallback added with this change scores that homepage at 67. GeoScore’s GEO column is its separate geo_score, not its overall score. Stripe is included as a public site with a Wikipedia article. The other nine are sites this team publishes.

08

The six answer measures

These six measures are the ask step. They belong to the same total as the ten page measures. The read step says whether a page can be fetched and quoted. The ask step says whether an answer names the campaign. Each measure is still shown on its own. A high mention rate with an inaccurate description, or with a negative tone, is two lines in one result, and both can lower the total.

The sample is four prompts on one engine, Grok, with web search, when an engine key is configured for the server. The recorded context is the prompt, the raw answer, the engine and surface, the date and time, country United States, account state “api”, the model name the API returns, and the visible citation URLs. This is not a logged-out consumer session on ChatGPT, Perplexity, Gemini, or Google, and it is not a market-wide rate. If the key is missing or the sample returns no text, each answer measure stays blank and the total is the page measures only.

Three prompts leave the campaign name out. They cover finding options and comparing options, for a voter or a buyer, in the city and state from the form. The fourth prompt names the campaign and asks for background, office, and contact information. That fourth prompt is for description accuracy only. It is not eligible for mention rate, answer position, or share of voice. A discovery prompt that already contains the brand is also ineligible, so the brand name cannot inflate mention rate.

  • Mention rate is the eligible answers that name the brand, divided by eligible answers. A direct name, an abbreviation, or a product name counts. A fuzzy reference, such as the domain with no name, is counted beside the rate and does not increase it.
  • Answer position is the first explicit mention of the brand. The buckets are first recommendation, inside the first three named options, a longer list, or a caveat rather than a recommendation. An ordered list uses the list order. With no list, the check uses the order the names appear in the text.
  • Competitor share of voice is this brand’s mentions divided by mentions of every name tracked in that same buyer, job, and stage. Names supplied as competitors count, and so do other names an answer lists. The check does not add those groups into one share.
  • Citation sources record the URL the answer shows and its root domain. Each domain is classed as your website, a review or directory, an editorial publication, a community or forum, a competitor website, or another third party. A domain is counted once in an answer, even when several visible URLs share it. Own-domain coverage is eligible answers that cite your domain, divided by eligible answers. An answer with no visible URL is “no visible citation.” It is not evidence that the model used no source. URLs a tool opened but did not show are stored apart from citations.
  • Description accuracy is graded only where the answer names the brand, against the phone on the page and the city, state, and office from the check. The grades are accurate, partly accurate, inaccurate, and unverifiable. Accurate scores 1, partly accurate scores 0.5, and inaccurate scores 0. Unverifiable answers are left out of the points.
  • Sentiment is the tone of those named answers: recommended, neutral, cautionary, or negative. Recommended scores 1, neutral 0.6, cautionary 0.3, and negative 0. The supporting sentence is kept with the raw answer. Sentiment does not change the accuracy grade.

Answer position turns the buckets into points: first recommendation 1, inside the first three 0.7, a longer list 0.35, and a caveat 0.2. Share of voice uses the mean of the prompt-group shares. The groups stay listed, and they are not added into one raw count. Own-domain citation coverage is the citation ratio.

A line under a signal still names a next step. Mention rate under 50 points to category relevance and third-party presence. Fewer than half of the named answers in the first recommendation or the first three points to differentiation and comparison evidence. Share of voice under 30 inside a prompt group points to the sources that support the names leading that group. Own-domain coverage under 25 points to source accessibility and external references. An inaccurate or partly accurate description points to the official facts on the page and to stale third-party profiles. A sample that is mostly cautionary or negative points to the pages that frame the brand that way.

09

Limits of this check

  • The check looks at one URL, plus robots.txt, llms.txt, and sitemap.xml on that origin. It does not fetch the pages listed in the sitemap.
  • An HTTP error page is still scored from the body that came back. A 403 or a short block page can look like a thin page. The result does not add a separate “could not read” status.
  • Words that exist only inside script are not counted. A script-rendered page can score as a page with very little readable text.
  • Pages that land in the same ratio buckets receive the same total, even when the businesses are unrelated.
  • Service credit depends on the fixed word list and the schema types named above. A page that never uses those words, and that has no matching schema type, does not get the service portion.
  • The robots match is a longest-prefix reading of the file. A host can still block a crawler outside robots.txt. This check does not see that.
  • Dates in an unexpected format are skipped. Freshness then falls through to the next date source, and then to the copyright year.
  • Allowing a crawler in robots.txt is evidence for this score. It does not cause that crawler to visit, and it does not cause a model to use the page.

10

What this check does not do

  • The four platform numbers do not query ChatGPT, Perplexity, Gemini, or Google. They reweight the 55 page points.
  • The ask step is added only when the sample returns text. It does not stand in for a logged-out session on those four products. A missing sample leaves the Visibility Method total at the 55 page points.
  • A four-prompt sample is not a market-wide mention rate, and a visible citation is not proof of which sources a model was trained on.
  • It does not control what a model says, which pages a model retrieves, or how an answer is ranked.
  • It does not change votes, turnout, indexing, or search rankings.
  • It does not promise leads, coverage, or a place in an AI answer.
  • It is not a substitute for a managed review of a campaign’s information, evidence, and distribution.

The free check is this one method: a read of one public page, then one labeled answer sample when the server has an engine key. Repeating the same prompts on a schedule is a separate managed measurement.

11

The form and the score

The scan request sends the URL, the campaign or committee name, the type, the city, and the state into one method run. The read step uses the public page. The ask step uses the name and place for the prompts and for the sentiment and accuracy grades. If the lead record fails, the score still stays on the page.

When the lead record succeeds, the page says the work email was recorded and that a person can follow up. The score is not emailed. The server writes a log line with the campaign name, email, URL, category, city, state, optional contact name, and the time. No phone number is collected.

Run the free AI visibility check on the campaign site you want scored. For the managed practice, see Election GEO.