Skip to content

AI answer audit

Twenty buyer questions in: who ChatGPT, Perplexity, Gemini and Google’s AI Mode name and cite for each, and whether any page of yours answers it.

Kind
Workflow
Price
98¢ per 20 questions
Your time
10 minutes
Approval
Runs on its own
Keyword.audit
You, to your agent

Check whether ChatGPT, Perplexity, Gemini and Google’s AI Mode name Leaseline for the 20 questions landlords ask most, spend up to $2, and show me the plan first.

curl -X POST "https://api.sb/leaseline.app/keywords/audit?mode=try" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"goal":"Check whether ChatGPT, Perplexity, Gemini and Google’s AI Mode name Leaseline for the 20 questions landlords ask most, spend up to $2, and show me the plan first.","budget":{"amount":2,"currency":"USD"}}'
npx startup-builder do Keyword.audit --try --data '{"goal":"Check whether ChatGPT, Perplexity, Gemini and Google’s AI Mode name Leaseline for the 20 questions landlords ask most, spend up to $2, and show me the plan first.","budget":{"amount":2,"currency":"USD"}}'
{
  "name": "do",
  "arguments": {
    "mode": "try",
    "code": "return await $.Keyword.audit({ goal: 'Check whether ChatGPT, Perplexity, Gemini and Google’s AI Mode name Leaseline for the 20 questions landlords ask most, spend up to $2, and show me the plan first.', budget: { amount: 2, currency: 'USD' } })"
  }
}
import { $ } from 'startup-builder'

const result = await $.try.Keyword.audit({ goal: 'Check whether ChatGPT, Perplexity, Gemini and Google’s AI Mode name Leaseline for the 20 questions landlords ask most, spend up to $2, and show me the plan first.', budget: { amount: 2, currency: 'USD' } })
Response
{
  "mode": "try",
  "stored": false,
  "estimate": "About 98¢ per 20 questions",
  "sample": {
    "question": "What is the best way for a small landlord to track rent?",
    "names you": "0 of 12 answers",
    "brands named": "keyrent.example, a spreadsheet",
    "cited most": "landlord-forum.example (9)",
    "your page": "none answers it"
  }
}
Try mode reads, stores nothing and spends nothingAPI referenceIts Nouns

What you get

  • 20 questions · Twenty buyer questions in: who ChatGPT, Perplexity, Gemini and Google’s AI Mode name and cite for each, and whether any page of yours answers it. · Keyword
  • share · Answers that name you, over all answers: 0.04 is 4 of every 100. A new domain reads 0 until a cited page of its own exists.
  • questions[].answers · For each engine: whether it names you, the brands it names, and the pages it cites.
  • questions[].yourPage · Your page that answers the question, with the quote that shows it does, or answers: false.
  • readiness · Whether robots.txt lets answer engines read the site, whether llms.txt exists, and the schema each key page carries.
  • citedDomains · The domains answers cite most, with counts: the pages to be listed on, or to pitch.

How long: About 2 minutes; ChatGPT answers take about 30 seconds each, asked in parallel.

Trigger

It runs when you call it. Search readout re-asks the saved questions every week.

TypeScript
every.week(($) => $.Keyword.track({ site: 'leaseline.app', terms: 'saved', questions: 'saved' }))

Steps

Your agent does these steps, one row per step; each step’s check is part of its row and its price.

StepVerbReturnsPriceApproval
1. Ask each engine each question three timesKeyword.askEach answer: the brands it names and the pages it citesAbout 96¢Runs on its own
2. Read the 20 pages answers cite mostPage.auditEach cited page’s content, for what it says that yours does notAbout 0.4¢Runs on its own
3. Audit your key pages for answer readinessPage.auditrobots.txt, llms.txt, schema and the first-60-words answer test on 10 pagesAbout 0.2¢Runs on its own
4. Check whether your page answers each questionDomain.verifyanswers: true with the quote code finds on your page, or answers: falseAbout 1¢Runs on its own
5. Count share and the gapsCollection.queryShare across every answer, and the questions no page of yours answersFreeRuns on its own

Calls: Keyword.ask, then Page.audit, then Domain.verify, then Collection.query.

About 98¢ per 20 questions, each time it runs, capped at $1.50.

Example: give it a goal

Check whether ChatGPT, Perplexity, Gemini and Google’s AI Mode name Leaseline for the 20 questions landlords ask most, spend up to $2, and show me the plan first.

The plan it shows runs 5 steps, priced before it spends anything; Run it above shows the result it returns.

When something fails

Each failure, and what happens next
WhenThen
An engine refuses or times out on every routeIt is left out of share and named under skipped; share is never computed over a missing engine.
An engine’s three answers disagreeAll three are kept on the Event, and share counts each; in goal mode the agent may ask that engine twice more and records the Decision with its cost.
Your site blocks answer engines in robots.txtreadiness.robotsAllowsAnswerEngines reads false and the readout leads with it: no page fix matters until crawlers can read the site.
You call it again the same dayIt returns the stored audit at $0, keyed on questions, site, engines and day.

Each step retries three times, then falls through to the next route; one item's failure lands in skipped with its reason, never failing the call. Before a step would cross maxCost it stops and returns what it has, with a resume link. Each step's idempotency key is the call's key plus the step and the item: leaseline-keyword-audit-1-<step>-<item>.

Change it

AskCompiles to
Add Claude and Copilot to the engines.Keyword.audit
Write an answer page for every question no page of mine answers.Page.answer
Ask these questions again every week and tell me what changed.Keyword.track
TypeScript
import { $, workflow } from 'startup-builder'

export default workflow({
  name: 'keyword-audit',
  verb: 'Keyword.audit',
  input: { questions: 'string[]', site: 'string', engines: 'string[]', runs: 'integer' },
  maxCost: 1.5,
  execute: async (ctx, { questions, site, engines = ['chatgpt', 'perplexity', 'gemini', 'google-ai-mode'], runs = 3 }) => {
    const answers = await ctx.step('answers', () => $.Keyword.ask({ questions, venues: engines, runs, maxCost: 1.1 }))
    const cited = await ctx.step('cited', () => $.Page.audit({ urls: topCited(answers, 20), fields: ['content'], maxCost: 0.02 }))
    const ready = await ctx.step('readiness', () => $.Page.audit({ site, pages: 10, checks: ['robots', 'llms', 'schema', 'first-answer'], maxCost: 0.01 }))
    const yours = await ctx.step('yours', () => $.Domain.verify({ hostname: site, answers: questions, fields: ['quote'], maxCost: 0.02 }))   // a checked extraction
    return auditOf(questions, answers, cited, ready, yours)
  },
})

Extend it with extends: 'Keyword.audit' and base(), or compose your own from these steps.

Works with

Plays that order it: Answer engine optimization, Make your API easy for agents to find, Developer relations, Free tools.

It serves Check AI answers, and runs in Launch and search. It deepens Content marketing.

For agents

For agents: the guide, its approvals, retries and lookups
FactValue
GuideKeyword.audit
Guide approvallimits
GoalCheck whether ChatGPT, Perplexity, Gemini and Google’s AI Mode name Leaseline for the 20 questions landlords ask most, spend up to $2, and show me the plan first. It may change counts, the order of steps, soft filters and the route a read takes, and it stops early when the goal is met. It never relaxes your words, raises its own budget, answers its own approval, calls a Play or acts outside your standing approval.
Triggerevery.week(($) => $.Keyword.track({ site: 'leaseline.app', terms: 'saved', questions: 'saved' }))
RetryThree times with backoff, then the next route; the same idempotency key never charges, sends or posts twice
Idempotency keyleaseline-keyword-audit-1
LookupsA find: input asks unless exactly one record fits
Step
1. Ask each engine each question three times
2. Read the 20 pages answers cite most
3. Audit your key pages for answer readiness
4. Check whether your page answers each question
5. Count share and the gaps

The amounts live once, on the hub (approvals).

Who does each step, and how it is checked
StepFunctionDoerCheckerAssuranceInputs
1. Ask each engine each question three timescodeCodeCode checks each result against its declared typemeasured$0.questions, $0.engines, $0.runs
2. Read the 20 pages answers cite mostcodeCodeCode checks each result against its declared typemeasured$1.cited
3. Audit your key pages for answer readinesscodeCodeCode checks each result against its declared typemeasured$0.site
4. Check whether your page answers each questionagenticThe Content lead agentCode finds the quoted evidence on the pagemeasured$0.site, $0.questions
5. Count share and the gapscodeCodeCode checks each result against its declared typemeasured$1, $2, $3, $4

The doer is never the checker, and the weakest assurance on the path is the whole call’s.

Under the hood

Under the hood: the Systems, Nouns and Events it touches
KindWhat it touches
SystemsNone.
NounsKeyword, Page, Domain, Collection
EventsDomain.verified, Collection.queried

Reference

Inputs, outputs, its Event and its errors
NameTypeDefaultMeaning
questionsstring[] | { fromMap: KeywordMap; take: number }RequiredThe questions buyers ask, in their words, or the question-form terms from a Keyword opportunity map.
siteHostnameRequiredYour site.
enginesVenueId[]['chatgpt', 'perplexity', 'gemini', 'google-ai-mode']The answer engines asked. Claude adds about 2.5¢ a question.
runsinteger3Asks per question per engine. Answers vary between asks; share is read across all of them.
maxCostnumber1.50The most this call spends each time it runs, in USD. It stops before a step would cross it and returns what it has, with a resume link.

Emits Keyword.audited. Refuses with max-cost before it spends, and with the Data calls and Accounts groups (refusals).

Contents