AnswerLine Start free

, updated , Tutorials · Perplexity · Brand Monitoring

Track brand mentions in Perplexity answers

To track brand mentions in Perplexity answers, run a fixed prompt set through Perplexity on a schedule, per market, and store each answer with its numbered sources. From each answer you read whether Perplexity named your brand, whether it cited your domain and how early, and how much of the answer rests on your pages. Perplexity cites every answer and maps each inline citation back to its source list, so citation position and coverage can be measured directly.

The fields are documented on the Perplexity engine page. If you are comparing ways to collect Perplexity answers rather than measuring them, see best Perplexity scrapers.

Definitions

The endpoint and request fields

POST https://api.answerline.dev/v1/monitor/perplexity, with Authorization: Bearer <key> (authentication).

Field Required Notes
prompt yes The prompt sent to Perplexity (up to 2,000 characters).
country yes Any country code; GET /v1/countries?model=perplexity lists supported values.
state no A US state code; implies country US. Perplexity answers for the whole US (states).
include.markdown no Adds result.markdown.
include.html no Adds result.html, a link to the answer’s public page on perplexity.ai.
include.rawResponse no Adds result.rawResponse, the answer as normalized stream events; include.rawWire returns null on Perplexity.

Step 1: send a prompt

curl

curl -X POST https://api.answerline.dev/v1/monitor/perplexity \
  -H "Authorization: Bearer $ANSWERLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Which project management tools do agencies use?",
    "country": "GB",
    "include": { "markdown": true }
  }'

Python (requests)

import os
import requests

API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['ANSWERLINE_API_KEY']}"}

resp = requests.post(
    f"{API}/v1/monitor/perplexity",
    headers=HEADERS,
    json={"prompt": "Which project management tools do agencies use?", "country": "GB"},
    timeout=660,
)
resp.raise_for_status()
result = resp.json()["result"]

for s in result.get("sources", []):
    print(s["position"], s["url"])

TypeScript (@answerline/sdk)

import { Client } from "@answerline/sdk";

interface PerplexityResult {
  text?: string;
  markdown?: string;
  sources?: { position: number; url: string; label?: string; description?: string }[];
  citationPills?: { citationPillId: number; position: number; url: string; domain: string; label: string }[];
  places?: { name: string; url?: string; rating?: number; address?: string[]; categories?: string[] }[];
}

const client = new Client({ apiKey: process.env.ANSWERLINE_API_KEY! });
const { result } = await client.monitor.perplexity<PerplexityResult>({
  prompt: "Which project management tools do agencies use?",
  country: "GB",
});
console.log((result.sources ?? []).map((s) => s.url));

The TypeScript SDK is on npm as @answerline/sdk; the Python examples call the HTTP endpoints with requests.

Step 2: the response fields

The body is { "success": true, "result": { ... } }.

Field Meaning
text The answer as plain text.
markdown The answer in Markdown, with include.markdown.
links[] The links in the answer text.
sources[] Every source, in order: position, url, label, description.
citationPills[] One entry per citation-group-and-source pair: citationPillId (1-based), position (1-based index into sources), url, domain, label, optional description. Empty when there are none.
places[] The places on the map Perplexity shows with the answer, hotels included: name, url, rating, address, lat, lng, categories, map_url, images.
images[] The pictures shown with the answer: title, url, thumbnail, source, and dimensions.
rawResponse[] The answer as normalized stream events, with include.rawResponse. result.rawWire (with include.rawWire) is null on Perplexity.

related_queries, search_model_queries, videos, hotels and shopping_cards are in the contract and come back empty. Perplexity-specific names such as map_url keep snake_case, while shared fields such as citationPills use camelCase; use the names exactly as returned.

Citation groups

Perplexity cites sources in bracketed groups such as [1][2][3]. Such a group comes back as three citationPills entries with the same citationPillId, each carrying its own url, domain and label. label is always present but may be empty; use domain or url to identify the source.

from collections import defaultdict

def citation_groups(result: dict) -> dict[int, list[int]]:
    groups = defaultdict(list)
    for pill in result.get("citationPills", []):
        groups[pill["citationPillId"]].append(pill["position"])
    return dict(groups)

A source cited in many groups carries more of the answer than one cited once. Count groups per domain as well as positions.

Step 3: brand metrics from a run

import re
from urllib.parse import urlsplit

def on_domain(url: str, domain: str) -> bool:
    host = (urlsplit(url).hostname or "").lower().removeprefix("www.")
    return host == domain or host.endswith("." + domain)

def perplexity_metrics(result: dict, aliases: list[str], domain: str) -> dict:
    brand = re.compile(r"\b(" + "|".join(re.escape(a) for a in aliases) + r")\b", re.IGNORECASE)
    positions = [s["position"] for s in result.get("sources", []) if on_domain(s["url"], domain)]
    groups = {p["citationPillId"] for p in result.get("citationPills", []) if on_domain(p["url"], domain)}
    places = [p.get("name", "") for p in result.get("places", [])]
    return {
        "mentioned": bool(brand.search(result.get("text", ""))),
        "cited": bool(positions),
        "best_position": min(positions) if positions else None,
        "groups_citing": len(groups),
        "in_places": any(brand.search(n) for n in places),
    }

Roll these up per prompt, market and run:

  1. Mention rate: share of answers naming the brand, cited or not (mentions vs citations).
  2. Citation rate: share of answers with cited.
  3. Average best position among cited answers. Lower is earlier in the list.
  4. Group coverage: average groups_citing, a measure of how much of the answer relies on your pages.
  5. Place presence, for local prompts: share of answers with places that list your business.

Word boundaries in the pattern stop “Acme” from matching “Acmeology”. For how many prompts a rate needs before you can report it, see how to measure brand mentions; the method is the same on every engine.

Step 4: run it at volume

A synchronous call waits for the full answer. For a prompt set, such as daily brand checks or a category watchlist, submit async tasks with a webhook and let results arrive as each completes:

[
  {
    "taskType": "PERPLEXITY",
    "payload": { "prompt": "Which project management tools do agencies use?", "country": "US" },
    "idempotencyKey": "pplx-pm-tools-agencies-US-2026-11-11",
    "webhook": { "url": "https://you.example/hook" }
  },
  {
    "taskType": "PERPLEXITY",
    "payload": { "prompt": "Which project management tools do agencies use?", "country": "GB" },
    "idempotencyKey": "pplx-pm-tools-agencies-GB-2026-11-11",
    "webhook": { "url": "https://you.example/hook" }
  }
]

POST that array to /v1/async/task/batch (1 to 500 tasks). With the SDK:

const markets = ["US", "GB"];
const tasks = markets.map((country) => ({
  taskType: "PERPLEXITY" as const,
  payload: { prompt: "Which project management tools do agencies use?", country },
  idempotencyKey: `pplx-pm-tools-agencies-${country}-2026-11-11`,
  webhook: { url: "https://you.example/hook" },
}));
const batch = await client.createBatch(tasks);
console.log(batch.summary); // { total, succeeded, failed }

Each item in results answers by index; failed items carry VALIDATION_ERROR, RESOURCE_ALREADY_EXISTS or INSUFFICIENT_CREDITS without affecting the rest. The webhook body is the GET /v1/async/task/{id} JSON, with the Perplexity result under response.result. Verify the signature (verify webhook signatures) and dedupe by task.id. For the batch-and-webhook plumbing, see the rank-tracking pipeline; for key design, idempotency keys explained.

What it costs

Per billing, at the Starter tier:

Request Price
Perplexity request $0.0015
include.markdown, include.html or include.rawResponse +0

Worked example: 40 prompts in 3 markets, weekly, is 40 x 3 x $0.0015 = $0.18 per run as tasks, or $0.72 for four weekly runs. A new account’s 100 free requests work on any engine. See pricing and cost planning.

Sync or async

Details in sync calls, async tasks or webhooks.

Pitfalls

Perplexity in a cross-engine program

Mention and citation rates on Perplexity are most useful next to the same numbers on other engines, such as Gemini and ChatGPT. Where you are cited on one and missing on another, compare the sources of both to see who takes the slot. How AI engines choose citations and running your own citation study go deeper; see also the AI visibility tracking use case.

See every field on the Perplexity engine page and in the API reference.

Questions

How do I track brand mentions in Perplexity?

Run a fixed prompt set through Perplexity on a schedule, per market, and store each answer. For every answer record whether the text names your brand, whether sources cites your domain and at what position, and how many citation groups cite you. Report those rates across runs, not from a single answer.

Which fields does a Perplexity result carry?

text, markdown (with include.markdown), links, sources, citationPills, places and images. citationPills is an empty list when the answer has none. related_queries, search_model_queries, videos, hotels and shopping_cards are in the contract but come back empty.

How do I rebuild Perplexity's bracketed citation groups?

Group result.citationPills by citationPillId. A group such as [1][2][3] appears as three entries sharing one citationPillId, each with its own url, domain and label, and position pointing into result.sources.

Does Perplexity show my business on its map?

For local prompts, result.places lists the places on the map Perplexity shows with the answer, each with name, url, rating, address, coordinates, categories and a map link. Match your business name against it to track local presence.

Can I monitor Perplexity in a specific US state?

No. Perplexity accepts a US state but answers for the whole US, the same as without it. See /docs/coverage#states.

Try it on your own prompts

100 free requests on any engine, no card. One POST returns the answer, sources and citations as JSON.

Keep reading