# Searchable Agent
Source: https://docs.searchable.com/advanced/ai-assistant
Get instant SEO and AEO recommendations from your AI-powered copilot
## Overview
Your AI Copilot Agent is an intelligent assistant that understands your website, business context, and SEO goals. It provides personalized recommendations and can take actions across your entire Searchable workspace.
The AI Copilot is available on all plans, with advanced actions unlocking on **Professional**, **Agency**, and **Custom** tiers.
## What Your AI Copilot Can Do
Review your visibility scores, prompt performance, and competitive position
Get prioritized, context-aware recommendations based on your data
Ask anything about your SEO, audit results, or AI visibility
Create prompts, generate content, analyze competitors, and more
## How to Access
Your AI Copilot is available throughout Searchable:
**From the Dashboard:**
* Click the **AI Assistant** icon in the top-right corner
* Available on any page within your workspace
* Maintains context of your current view
**From Specific Pages:**
* **Pages Tab**: Right-click any page → "Ask AI" for page-specific recommendations
* **Issues Tab**: Click any issue → "Get AI Help" for fix guidance
* **Prompts Tab**: Select prompts → "Optimize with AI" for improvement suggestions
The AI Copilot learns from your knowledge base (created in Step 1 of the onboarding checklist), so train it well for better recommendations!
## Core Capabilities
### 1. Website Analysis
Ask your copilot to analyze any aspect of your site:
**Example questions:**
* "What are my biggest SEO issues right now?"
* "Why is my technical score low?"
* "Which pages should I optimize first?"
* "How do I improve my Core Web Vitals?"
**What it does:**
* Reviews your latest audit data
* Identifies patterns across issues
* Prioritizes by impact and effort
* Provides step-by-step fix instructions
### 2. Visibility & Competitive Intelligence
Get insights into your AI visibility and competitors:
**Example questions:**
* "How am I performing against competitors?"
* "Which prompts are getting the most mentions?"
* "Why isn't \[competitor] being cited for \[topic]?"
* "What content gaps exist in my category?"
**What it does:**
* Analyzes visibility reports across 4 AI platforms
* Compares your performance to competitors
* Identifies opportunity topics
* Recommends content strategy
### 3. Prompt Optimization
Improve your AI visibility tracking:
**Example questions:**
* "Can you analyze my prompt performance?"
* "Generate 10 new prompts for \[topic]"
* "Why aren't my prompts getting mentions?"
* "Optimize this prompt: \[your prompt]"
**What it does:**
* Reviews prompt mention rates
* Generates industry-specific prompts
* Suggests improvements to existing prompts
* Identifies zero-mention opportunities
### 4. Content Strategy
Plan and create optimized content:
**Example questions:**
* "What content should I create next?"
* "Generate a blog post about \[topic]"
* "How do I optimize my existing article on \[topic]?"
* "What keywords should I target?"
**What it does:**
* Identifies content gaps
* Generates AI-optimized articles
* Provides SEO and AEO recommendations
* Suggests internal linking opportunities
### 5. Integration Assistance
Get help with connected platforms:
**Example questions:**
* "Show me my Google Search Console data"
* "What keywords am I ranking for?"
* "Analyze my GA4 traffic from AI platforms"
**What it does:**
* Retrieves data from connected integrations
* Correlates metrics across platforms
* Provides unified insights
* Assists with publishing workflows
### 6. Technical SEO Guidance
Understand and fix technical issues:
**Example questions:**
* "Explain this issue: \[paste issue title]"
* "How do I implement structured data?"
* "What's causing my slow page speed?"
* "Walk me through fixing 404 errors"
**What it does:**
* Explains technical concepts clearly
* Provides code examples and instructions
* Estimates impact of fixes
* Offers best practices
## Advanced Features
### Context Awareness
Your AI Copilot understands:
* **Your current page**: Automatically knows where you are in the app
* **Your project**: Aware of your domain, industry, and goals
* **Your data**: Has access to all your metrics and history
* **Your knowledge base**: Trained on your brand information
### Multi-Turn Conversations
Build on previous questions:
```text theme={null}
You: "What are my critical issues?"
Copilot: [Lists 5 critical issues]
You: "Explain the first one in detail"
Copilot: [Detailed explanation with fix steps]
You: "Generate the code for that fix"
Copilot: [Provides implementation code]
```
### Available Actions
The copilot can execute tasks on your behalf:
* Create new prompts
* Generate content outlines and articles
* Run SERP analysis
* Fetch competitor data
* Analyze keyword opportunities
* Export reports
Analyze data, answer questions, provide recommendations
Create prompts, generate content, optimize pages (with confirmation)
## Copilot Tiers by Plan
| Capability | Starter (\$100) | Professional (\$300) | Agency (\$750) | Custom |
| ---------------------------- | --------------- | -------------------- | -------------- | ------ |
| **Basic Analysis** | ✓ | ✓ | ✓ | ✓ |
| **Prompt Generation** | ✓ | ✓ | ✓ | ✓ |
| **Content Creation** | ✓ | ✓ | ✓ | ✓ |
| **Integration Data** | — | ✓ | ✓ | ✓ |
| **Competitor Analysis** | — | ✓ | ✓ | ✓ |
| **Advanced Analytics** | — | ✓ | ✓ | ✓ |
| **Batch Actions** | — | Limited | ✓ | ✓ |
| **Custom Tools & Workflows** | — | — | Limited | ✓ |
## Best Practices
Start conversations with specific questions, not vague requests
Reference specific pages, prompts, or issues for targeted help
Review AI-generated content before publishing
Use copilot for second opinions on strategies
Build multi-turn conversations for complex topics
The AI Copilot provides recommendations based on your data and industry best practices. Always verify critical changes before implementing, especially technical modifications.
## Example Workflows
### Morning SEO Check
```text theme={null}
You: "What changed overnight? Any critical issues?"
Copilot: Analyzes latest data and highlights:
- New critical issues (if any)
- Significant score changes
- Visibility improvements or drops
- Recommended immediate actions
```
### Content Planning Session
```text theme={null}
You: "I need content ideas for next month"
Copilot:
1. Analyzes your zero-mention prompts
2. Identifies top opportunities
3. Suggests 5-10 article topics
4. Provides target keywords and structure
You: "Create an outline for the first topic"
Copilot: Generates comprehensive outline with:
- SEO-optimized headlines
- Section structure
- Internal linking suggestions
- Target word count
```
### Issue Resolution
```text theme={null}
You: "How do I fix my Core Web Vitals?"
Copilot:
1. Reviews your specific CWV metrics
2. Identifies root causes
3. Prioritizes fixes by impact
4. Provides code examples
5. Estimates score improvement
You: "Implement the first fix"
Copilot: Provides step-by-step implementation guide
```
## Privacy & Data
**What the copilot knows:**
* Your project data (scores, issues, prompts, content)
* Your knowledge base (brand info you provided)
* Your connected integration data
* Industry benchmarks and best practices
**What stays private:**
* All conversations are private to your account
* No data shared with external AI models beyond necessary processing
* Training data stays within Searchable
* You own all generated content and insights
## Conversation Management
**Chat History:**
* All conversations are saved automatically
* Access past conversations from the sidebar
* Search through conversation history
* Delete conversations anytime
**New Conversation:**
* Click "New Chat" to start fresh context
* Previous conversations remain accessible
* Each chat maintains its own context
## Limitations
The AI Copilot is powerful but has boundaries:
**What it won't do:**
* Make changes without your confirmation for write operations
* Access websites outside your verified properties
* Share your data with third parties
* Guarantee specific ranking improvements (provides best practices only)
## Tips for Best Results
### Be Specific
**Instead of:** "Help with SEO"\
**Try:** "Why is my technical score 62 and how can I get it to 80?"
### Provide Context
**Instead of:** "Fix this issue"\
**Try:** "Explain this issue '\[paste issue title]' and show me how to fix it on a WordPress site"
### Build on Responses
**Multi-turn approach:**
1. Ask for analysis first
2. Request detailed explanation
3. Get implementation steps
4. Ask for code examples
5. Request expected impact
### Use for Planning
**Strategic questions:**
* "Create a 30-day plan to improve AI visibility"
* "What should I focus on this week?"
* "Prioritize my issues by ROI"
* "Build a content calendar for Q1"
## Getting Help
If the copilot doesn't have enough context:
* Ensure you've completed the knowledge base setup
* Verify your project is properly configured
* Check that integrations are connected (for integration data)
* Try rephrasing your question more specifically
## Next Steps
Update knowledge base for better recommendations
Use copilot to create optimized content
Optimize prompts with AI assistance
Get AI help fixing audit issues
# Advanced API Usage
Source: https://docs.searchable.com/advanced/api-usage
Query your AI visibility data and generate reports programmatically with the Searchable API
## Overview
Searchable exposes three programmatic surfaces. Pick the one that fits your use case:
30+ read tools for Claude, Cursor, and other MCP clients — the richest way to query your data.
Fetch audits & issues and generate shareable reports with an API key — see the interactive
reference + playground.
Send AI-bot traffic events from any language or platform.
API access requires a **paid Searchable plan** — API keys can't be created on the Free plan.
## Authentication
Create an API key in **Settings → Workspace → Integrations** in your Searchable dashboard. Keys start with `sea_` and are shown only once — store it securely.
Send it as a Bearer token on every request:
```
Authorization: Bearer sea_your_key_here
```
| Base URL | `https://app.searchable.com` |
| -------- | ---------------------------- |
### Scopes
Each key carries one or more scopes. Read endpoints require `read` (the default); write endpoints require `write`.
| Scope | Grants |
| ------- | -------------------------------------------- |
| `read` | Fetch audits, issues, and visibility data |
| `write` | Everything in `read`, plus report generation |
| `admin` | All scopes |
A key can also be **bound to a single project**. A project-bound key only works against that project; leave a key unbound to use it across all projects you can access.
## Fetch audits + issues
Retrieve the latest audit per page, when each was last completed, and optionally the open issues for each page.
```
GET /api/v1/projects/{projectId}/audits?includeIssues=true
```
```javascript theme={null}
const res = await fetch(
"https://app.searchable.com/api/v1/projects/PROJECT_ID/audits?includeIssues=true",
{ headers: { Authorization: "Bearer sea_YOUR_KEY" } }, // requires the `read` scope
);
const { summary, audits } = await res.json();
// summary.totalPages — pages with at least one completed audit (not all tracked pages)
// summary.lastCompletedAt — newest completed audit across all pages
// audits[].openIssues — present only when includeIssues=true
```
## Share of voice & competitors
Brand vs competitor share of voice, and the project's real/tracked competitor roster (also available as the `get_share_of_voice` and `get_competitors` MCP tools). All four endpoints accept the same filter family: `days`, `platform`, `topicId`, `unbranded`/`branded`, `country`/`locationId`.
```
GET /api/mcp/projects/{projectId}/share-of-voice
GET /api/mcp/projects/{projectId}/share-of-voice/history
GET /api/mcp/projects/{projectId}/competitors
GET /api/mcp/projects/{projectId}/competitors/{competitorId}
```
```javascript theme={null}
const res = await fetch(
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/share-of-voice?days=30",
{ headers: { Authorization: "Bearer sea_YOUR_KEY" } }, // requires the `read` scope
);
const { brand, competitors, dateRange } = await res.json();
// brand.delta / competitors[].delta are day-over-day (today vs yesterday),
// not a comparison against a prior period the length of `days`.
// mentions/citations are always null on this endpoint — call
// GET .../competitors or GET .../competitors/{competitorId} for those counts.
```
Two things to know on the competitors endpoints: the list view's `mentions` is an **all-time** count that ignores `days` and the filters (mirrors the in-app Competitors list), and the detail view carries **two distinct metrics** — the top-level `citations` counts inline citations on responses that *mention* the competitor (any domain), while `history[].domainSources` counts source URLs (pages the engines consulted for generation, not inline citations) on the competitor's *own* domain.
## AI Traffic API
First-party AI-traffic measurement — crawler visits and AI-referral sessions sourced from the tracker/CDN pipeline (also available as the `get_ai_traffic` MCP tool, `report=overview|crawlers|referrals|top_cited_pages`).
```
GET /api/mcp/projects/{projectId}/traffic/overview
GET /api/mcp/projects/{projectId}/traffic/bots
GET /api/mcp/projects/{projectId}/traffic/referrals
GET /api/mcp/projects/{projectId}/traffic/top-cited-pages
```
```javascript theme={null}
const res = await fetch(
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/traffic/overview?days=30",
{ headers: { Authorization: "Bearer sea_YOUR_KEY" } }, // requires the `read` scope
);
const { crawlers, referrals, topPages, dateRange } = await res.json();
// crawlers.total / referrals.total are window totals; byPlatform breaks each
// down by AI platform (openai, anthropic, google, perplexity, microsoft, …).
// topPages is crawl-ranked (top 10) — its `referrals` field is always null;
// call top-cited-pages with a platform for per-page AI-referral counts.
```
`bots` returns a paginated per-page crawler-activity list — `items[]` (each with a `byPlatform` breakdown), and `pagination` (`limit`/`offset`/`returnedCount`/`hasMore`/`nextOffset`; `totalCount` is always `null` since the underlying per-vendor query doesn't cheaply support an exact cross-platform total). `referrals` returns a daily AI-referral session timeseries by platform plus window `totals`. `top-cited-pages` **requires** an explicit `platform` (one of `openai`, `anthropic`, `google`, `perplexity`, `microsoft`) and returns `400` without one. `platform` is validated strictly on every endpoint that accepts it: an unrecognized value returns `400` listing the supported keys (`bots`/`referrals` accept the full eight-platform set — the five above plus `deepseek`, `xai`, `meta`) — never a silent empty result.
All four endpoints return `409 { code: "traffic_not_connected", message, howToFix }` when the project has no crawler-log, CDN, or Searchable-tracker source connected — `howToFix` links straight to **AI Traffic → Setup** in the dashboard. Connect a source there, then retry.
## Shopping visibility
AI shopping/product visibility (Peec-parity) — products surfaced in AI shopping/product-carousel responses (also available as the `get_shopping_visibility` MCP tool, `view=summary|timeseries`, or pass `productId` for detail).
```
GET /api/mcp/projects/{projectId}/shopping
GET /api/mcp/projects/{projectId}/shopping/products/{productId}
GET /api/mcp/projects/{projectId}/shopping/timeseries
```
```javascript theme={null}
const res = await fetch(
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/shopping?days=30",
{ headers: { Authorization: "Bearer sea_YOUR_KEY" } }, // requires the `read` scope
);
const { available, products, summary, dateRange } = await res.json();
// available:false (200, not an error) means no shopping/product data yet —
// this is a data-presence state, not a broken integration. It appears
// automatically once tracked prompts trigger an AI shopping carousel.
// products[].platforms is a single-element array (the product's one
// dominant platform) — call the product-detail endpoint below for a real
// per-platform breakdown.
```
`productId` is the product's raw title (the `id` returned by the list endpoint above) — percent-encode it in the URL. The detail endpoint returns occurrences, vendor/pricing rows, a **real** per-platform breakdown, and up to 50 recent responses that surfaced the product. Requires a plan with **Shopping Analytics** (Scale or higher) — returns `403 { requiresUpgrade: true }` if the workspace's plan doesn't include it and the project has data to fetch (an empty project still returns `available:false` first).
## Ads
Sponsored ads surfaced in AI answers — who is advertising, the actual ad creatives, ad-heavy prompts, and the frequency trend (also available as the `get_ads` MCP tool, `view=advertisers|creatives|prompts|timeseries`).
```
GET /api/mcp/projects/{projectId}/ads/advertisers
GET /api/mcp/projects/{projectId}/ads/creatives
GET /api/mcp/projects/{projectId}/ads/prompts
GET /api/mcp/projects/{projectId}/ads/timeseries
```
```javascript theme={null}
const res = await fetch(
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/ads/advertisers?days=30",
{ headers: { Authorization: "Bearer sea_YOUR_KEY" } }, // requires the `read` scope
);
const { advertisers, brand, totals, pagination } = await res.json();
// advertisers are ranked by ad volume; `brand` is your own ad share of voice
// and rank among advertisers (null when you're not advertising). adCount /
// appearances count ads we scraped in AI answers, not ad-platform impressions.
```
`/ads/advertisers` is offset-paginated (`{limit, offset, returnedCount, totalCount, hasMore, nextOffset}`); pass an advertiser's `advertiserKey` into `/ads/creatives` or `/ads/timeseries` to drill into one advertiser. `/ads/creatives` also accepts `promptId` and a free-text `search`; `/ads/prompts` accepts `sortBy` (`promptText|adUnits|coveragePct|engines|totalResponses`) + `sortDir`. All windows follow `days` (default 30, max 365). Ad data appears once tracked prompts surface sponsored ad units. `promptId` takes a prompt ID, not prompt text — an unrecognized ID matches nothing rather than erroring, so an empty result can mean an unresolved filter as well as no captured data. These endpoints take no topic or location filters; use the `get_ads` MCP tool for those.
## Brand profile & domain authority
The knowledge-base brand profile plus AI-observed brand facts, and the domain's Moz authority history (also available via the `get_brand_profile` MCP tool, which takes `include: "domain_authority"` for the Moz block).
```
GET /api/mcp/projects/{projectId}/brand-profile
GET /api/mcp/projects/{projectId}/domain-authority
```
```javascript theme={null}
const res = await fetch(
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/brand-profile",
{ headers: { Authorization: "Bearer sea_YOUR_KEY" } }, // requires the `read` scope
);
const { profile, facts, factCount } = await res.json();
// profile is the user-curated knowledge base (null until onboarding creates
// one): brand name, headline, category, positioning, description, topics,
// business type, connected entities, competitor geography/context.
// facts[] is the latest weekly batch of statements AI platforms actually make
// about the brand — filter with ?platform= and ?verificationStatus=
// (unverified | pass | fail).
```
`domain-authority` returns the latest Moz snapshot (`domainAuthority`, `pageAuthority`, `spamScore`, `linkingRootDomains`, `fetchedAt`) plus `history[]` over `days` (default 365, max 1095 — snapshots are roughly monthly). It reads the app-maintained cache only and never triggers a live Moz fetch: `latest` is the newest snapshot regardless of the window, and `latest: null` means the app hasn't fetched DA for this project yet.
## Prompt catalog
The project's prompt configuration — what it monitors, what's paused, and what the AI has suggested but nobody has reviewed yet (also available as the `list_prompts` MCP tool). This is configuration data, not performance: for per-prompt visibility scores use `/visibility/prompts`.
```
GET /api/mcp/projects/{projectId}/prompts
```
```javascript theme={null}
const res = await fetch(
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/prompts?status=tracked",
{ headers: { Authorization: "Bearer sea_YOUR_KEY" } }, // requires the `read` scope
);
const { summary, prompts, pagination } = await res.json();
// summary always reports all three counts: { tracked, untracked, suggested }.
// Tracked/untracked prompts carry type, intent, branded flag, topics,
// tracked locations, and keyword volume/difficulty.
```
`status` selects the slice: `tracked` (default — actively monitored), `untracked` (paused), `all` (both), or `suggested` — the pending review queue of AI-proposed prompts (from research runs and the agent) that nobody has accepted or rejected yet, each with the `reason` it was proposed and its `source`. Accepted suggestions graduate into the tracked catalog and leave the queue. `topicId` restricts any slice to one topic; `limit` (default 50, max 200) + `offset` paginate with the standard `pagination` shape.
## Prompt answers
Raw, per-response AI-answer data for one prompt (Profound-parity) — platform, response date, response text, brand/competitor mentions, and the source URLs the engine consulted (`sources[]` — pages used for generation, not inline citations), one entry per AI response (also available as the `get_prompt_answers` MCP tool).
```
GET /api/mcp/projects/{projectId}/prompts/{promptId}/responses
```
```javascript theme={null}
const res = await fetch(
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/prompts/PROMPT_ID/responses?days=30&limit=10",
{ headers: { Authorization: "Bearer sea_YOUR_KEY" } }, // requires the `read` scope
);
const { prompt, responses, pagination } = await res.json();
// responses[].text is hard-truncated at 2000 characters; responses[].truncated
// signals the cut. citations only includes source-type citations (the same
// filter /api/analytics/visibility/query-detail applies).
```
`limit` is clamped to 1–50 (default 10); `?limit=0` clamps to 1, it never silently falls back to the default. `pagination` follows the standard `{limit, offset, returnedCount, totalCount, hasMore, nextOffset}` shape (see [Pagination](/integrations/mcp#pagination)). Returns `404` if `promptId` doesn't exist or belongs to a different project.
## Generate a shareable report
Generate and publish a report, and get back its public share URL. Also available as the `generate_report` MCP tool (requires the **write** scope and an explicit `confirm: true`); this REST endpoint is the direct path.
```
POST /api/mcp/projects/{projectId}/reports
GET /api/mcp/projects/{projectId}/reports
```
```javascript theme={null}
const res = await fetch("https://app.searchable.com/api/mcp/projects/PROJECT_ID/reports", {
method: "POST",
headers: {
Authorization: "Bearer sea_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
reportType: "combined", // "sentiment" | "visibility" | "combined" (default "sentiment")
timeRange: "30d", // "7d" | "30d" | "90d" | "365d" (default "30d")
status: "published", // "published" | "draft" (default "published")
// optional filters: platforms, topicIds, locationIds (string arrays)
// optional: title, unbrandedOnly, brandedOnly
}),
});
const { shareUrl, shareToken, reportType, success } = await res.json();
```
`POST` requires the `write` scope and a plan that includes report sharing.
`GET /reports?limit=20&offset=0` (requires only the `read` scope) lists previously generated reports for the project, newest first — `{ reports: [{id, reportType, title, status, shareUrl, createdAt}], pagination }`. It lists every currently-public report in the project (any project member's, not just reports the calling key's user created); drafts and unshared reports are excluded — a report saved with `status: "draft"` won't appear until published, and one that's later unshared drops off too.
## Period comparison
`GET /visibility`, `GET /visibility/topics`, `GET /share-of-voice`, and `GET /sentiment` answer "vs last period" in one call — pass `compare=previous_period` or `compare=previous_year`:
```bash theme={null}
curl -H "Authorization: Bearer $SEARCHABLE_API_KEY" \
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/visibility?days=30&compare=previous_period"
```
Windows are whole UTC calendar days and never overlap: `previous_period` spans the same number of calendar days as the current window and ends the day **before** the current window's first day; `previous_year` is the current window's calendar days shifted back exactly 365 days. The `comparison.dateRange` in the response is exactly the range the previous-period query ran over. The response gains an additive `comparison` block — nothing else changes shape:
```json theme={null}
{
"summary": { "visibilityScore": 45.5, "...": "..." },
"comparison": {
"mode": "previous_period",
"dateRange": { "from": "2026-06-11T00:00:00.000Z", "to": "2026-07-11T23:59:59.999Z" },
"previous": { "visibilityScore": 40, "totalResponses": 180, "...": "..." },
"delta": { "visibilityScore": 5.5, "totalResponses": 20 }
}
}
```
`delta` is current minus previous for every metric computable on both sides — a metric that can't be compared is absent, never a fabricated `0`. On `/share-of-voice`, competitor rows additionally carry `previousSov` / `sovDelta` inline (matched by entity display name — the share-of-voice entity identity); on `/visibility/topics`, each topic row carries `comparison.previousMentionedPercentage` / `mentionedPercentageDelta`. On the MCP `get_visibility` tool, `compare` works with `group_by=summary` and `platform`; `prompt` and `location` return `invalid_argument` rather than silently ignoring it.
## Per-URL metrics rollup
One page's three AI series in one call — AI-answer activity citing the URL, AI-referral sessions landing on it, and AI-crawler hits fetching it:
```bash theme={null}
curl -H "Authorization: Bearer $SEARCHABLE_API_KEY" \
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/pages/metrics?url=/pricing&days=90"
```
`url` is a full URL or a bare path (resolved against the project's domain); a query string is kept, so `/watch?v=abc` and `/watch?v=xyz` are distinct pages. The citation series reports two distinct numbers — `inlineCitations` (the AI answer linked the URL in its text) and `sourceUses` (a model consulted the URL as a source), with daily `sourceUses` buckets. The two traffic series are scoped to the verified project domain the URL's host resolves to and return `available: false` with a `reason`: `traffic_not_connected` when the [LLM Analytics integration](/setup/overview) isn't connected, or `external_url` for a host outside the project's verified domains (external pages get cited too, so the citation series still answers). A citation-lookup failure likewise degrades just that series (`citation_lookup_failed`) rather than reading as a fake zero.
## Query visibility, sources & sentiment
For visibility scores, share of voice, sources, sentiment, shopping visibility, AI ads, raw AI answers, AI traffic, and GA4/GSC data, connect the **[MCP server](/integrations/mcp)** — it exposes read-only tools over the same data and handles auth for you. It's the fastest path for read-heavy automation and works directly inside Claude, Cursor, and other assistants.
## Send AI-bot traffic
To report request events from your own app or CDN (so crawlers like GPTBot and ClaudeBot show up in your dashboard), use the **[REST Ingest API](/setup/rest-api)**. That endpoint uses a separate ingest key (`sk_live_…`) and a signed edge path — see its page for the full contract.
## Rate limiting
Every API key is limited to **600 requests/minute** across the REST surface (`/api/mcp/*`, `/api/v1/*`, and the Looker Studio connector — MCP tool calls have their own separate concurrency limits, not this budget). Two exceptions: `/api/v1/chat` and `/api/v1/chat/stop` don't count against this budget and don't emit the rate-limit headers below (`/api/v1/chat` has its own chat-specific limiter). Every other response carries rate-limit headers, whether it succeeds or errors:
```
RateLimit: "default";r=598;t=42
RateLimit-Policy: "default";q=600;w=60
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 598
X-RateLimit-Reset: 1755000042
```
`RateLimit`/`RateLimit-Policy` follow the [IETF rate-limit header draft](https://www.ietf.org/archive/id/draft-ietf-httpapi-ratelimit-headers-08.html) (`r` = remaining, `t` = seconds until reset, `q` = quota, `w` = window in seconds). `X-RateLimit-*` is kept alongside for clients that read the older convention; `X-RateLimit-Reset` is an absolute Unix-epoch second.
The limiter fails open: if its backing store is briefly unavailable, requests are **allowed** (never refused for infrastructure reasons) and the rate-limit headers are omitted from those responses — don't hard-require the headers in client code.
Exceeding the limit returns `429` with a `Retry-After` header (seconds) and a `rate_limited` problem+json body — see the [error reference](/api/errors#rate-limited).
```javascript theme={null}
const res = await fetch("https://app.searchable.com/api/mcp/projects", {
headers: { Authorization: "Bearer sea_YOUR_KEY" },
});
if (res.status === 429) {
const retryAfter = Number(res.headers.get("Retry-After") ?? "60");
// wait retryAfter seconds, then retry
}
```
## Idempotency
The three mutating POST endpoints — `POST /reports`, `POST /audits`, and `POST /sitemap/refresh` — accept an `Idempotency-Key` header. Send the same key on a retry (e.g. after a timeout or a dropped connection) and the API replays the original response instead of repeating the side effect (generating a second report, starting a second audit run, or a second sitemap sync):
```javascript theme={null}
const idempotencyKey = crypto.randomUUID();
const res = await fetch("https://app.searchable.com/api/mcp/projects/PROJECT_ID/reports", {
method: "POST",
headers: {
Authorization: "Bearer sea_YOUR_KEY",
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey,
},
body: JSON.stringify({ reportType: "sentiment" }),
});
// A retry with the SAME idempotencyKey returns the same body and adds:
// X-Idempotent-Replay: true
```
Notes:
* Keys are scoped per API key and held for **24 hours**.
* Only a **successful (2xx)** response is stored — a failed attempt (4xx/5xx) is never replayed, so retrying after a real failure with the same key simply runs the request again.
* Two **concurrent** requests with the same key never both execute: the second gets `409` (`code: "idempotency_in_flight"`) with `Retry-After: 5` while the first is still running. Wait, then retry with the same key — you'll receive the first request's stored response once it completes (or a fresh run if it failed). See the [error reference](/api/errors#idempotency-in-flight).
* A stored response body over **100KB** is not cached — the request still runs normally, and the response carries `X-Idempotent-Skipped: body-too-large` instead of `X-Idempotent-Replay`.
* Keys are **not** fingerprinted to the request body: reusing a key with a *different* body returns the stored response from the first request. Use a fresh key for each distinct operation.
* No `Idempotency-Key` header — the request behaves exactly as before; this is fully opt-in.
## Error handling
Full reference with remediation for every error code: **[API Error Reference](/api/errors)**.
| Status | Meaning |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400` | Bad request — check parameters / body (`code: "invalid_argument"` and related validation codes) |
| `401` | Missing or malformed API key (`code: "unauthorized"`) |
| `403` | Insufficient scope, plan gate, quota exceeded, or a paused/pitch project (`missing_scope`, `plan_upgrade_required`, `quota_exceeded`, `project_not_runnable`, `pitch_not_supported`) |
| `404` | Project not found, or the key isn't allowed to reach it (`code: "not_found"`) |
| `409` | Integration not connected — GSC/GA4 endpoints return `{ code: "gsc_not_connected" \| "ga4_not_connected", message, howToFix }` when the project has no linked Search Console site / GA4 property (connect in **Settings → Integrations**); AI Traffic endpoints return `{ code: "traffic_not_connected", message, howToFix }` when no crawler-log, CDN, or tracker source is connected (connect in **AI Traffic → Setup**). Retry after connecting |
| `429` | Rate limit exceeded — see [Rate limiting](#rate-limiting) above (`code: "rate_limited"`, `Retry-After` header) |
| `500` | Server error — retry with exponential backoff (`code: "internal_error"`) |
| `504` | The query or report generation timed out — retryable (`code: "query_timeout"`) |
Every error body is `application/problem+json`: alongside the original `error` string (unchanged, for existing integrations), it now also carries `type`, `title`, `code`, `message`, and `requestId`. See the [error reference](/api/errors) for the full body shape and every code.
## API key best practices
Never commit API keys to version control — use environment variables
Scope each key to the minimum it needs (`read` unless it must write)
Bind a key to a single project when it only ever touches that project
Use separate keys for dev and prod, and rotate them regularly
Revoke compromised keys immediately in Settings → Integrations
## Need more?
Higher rate limits, custom endpoints, or a dedicated integration? Contact **[support@searchable.com](mailto:support@searchable.com)**.
## Next steps
Connect Claude, Cursor, and other assistants to your Searchable data.
Send AI-bot traffic events from any stack.
# Advanced Custom Prompts (Beta)
Source: https://docs.searchable.com/advanced/custom-prompts
Master advanced prompt techniques for maximum AI visibility
## Overview
Advanced prompt customization allows you to create sophisticated tracking strategies using variables, templates, and automation.
## Features
* **Prompt Variables**: Dynamic prompts that adapt to context
* **Conditional Logic**: Different prompts based on user segments
* **A/B Testing**: Test prompt variations for effectiveness
* **Batch Operations**: Manage hundreds of prompts efficiently
* **Performance Analytics**: Deep dive into prompt metrics
## Variable System
Use variables in prompts:
```text theme={null}
What are the best {category} for {audience} in {year}?
```
Variables auto-populate based on your settings.
## Templates & Patterns
* Save successful prompts as templates
* Apply patterns across multiple prompts
* Industry-specific template libraries
* Custom template creation
## Automation
* Auto-generate prompts from keywords
* Schedule prompt activations
* Retire underperforming prompts automatically
* Smart prompt suggestions
## Custom Capabilities
* Multi-language prompt management
* Team collaboration on prompts
* Advanced attribution modeling
* Custom reporting dashboards
Learn more in [Working with Prompts](/using-searchable/working-with-prompts).
# Teams & Collaboration (Beta)
Source: https://docs.searchable.com/advanced/teams-collaboration
Manage team members, permissions, and collaborative workflows
## Overview
Searchable's team features enable collaborative SEO and AEO management with role-based access control and shared dashboards.
## Team Roles
### Administrator
* Full access to all features
* Can invite/remove team members
* Manage billing and subscriptions
* Configure integrations
### Editor
* Edit content and settings
* Run audits
* Manage prompts
* View analytics
* Cannot manage team or billing
### Viewer
* Read-only access
* View dashboards and reports
* Export data
* Cannot make changes
## Managing Team Members
Settings → Team → Invite Member
* Enter email address
* Select role
* Send invitation
* Receives email invitation
* Creates account or signs in
* Gains access based on role
* Change roles anytime
* Suspend access temporarily
* Remove members
* Track activity
## Agency & Custom Features
Advanced security features (SSO, audit trails, custom roles) are included with Custom contracts. Agency customers can request specific capabilities through their success manager.
### SSO/SAML
* Single sign-on integration
* Azure AD, Okta, Google Workspace
* Automatic user provisioning
* Centralized access management
### Advanced Permissions
* Custom role creation
* Granular feature permissions
* Project-level access control
* IP whitelisting
### Audit Trails
* Complete activity logs
* Compliance reporting
* Change history
* Security monitoring
## Best Practices
Assign clear responsibilities per team member
Use comments for collaborative decision-making
Regular team check-ins on progress
Shared optimization priorities
## Next Steps
Start collaborating
See how the AI assistant supports teamwork
# Get AI-ad frequency timeseries
Source: https://docs.searchable.com/api-reference/ads/get-ai-ad-frequency-timeseries
/api-reference/openapi.json get /api/mcp/projects/{projectId}/ads/timeseries
Per-advertiser daily ad-frequency trend — one series per top advertiser (brand force-included), each with a { date, adCount } array, plus the filtered-window total ad appearances. `days` defaults to 30, max 365.
# List ad-surfacing prompts
Source: https://docs.searchable.com/api-reference/ads/list-ad-surfacing-prompts
/api-reference/openapi.json get /api/mcp/projects/{projectId}/ads/prompts
Which tracked prompts surface the most sponsored ads — per-prompt ad-unit count, ad coverage percent (share of the prompt's responses that carried an ad), response count, and the AI engines that surfaced ads. Server-sorted. `days` defaults to 30, max 365.
# List AI-ad advertisers
Source: https://docs.searchable.com/api-reference/ads/list-ai-ad-advertisers
/api-reference/openapi.json get /api/mcp/projects/{projectId}/ads/advertisers
Who is running sponsored ads in AI answers, ranked by scraped ad-appearance volume, plus the brand's own ad share of voice + rank (or null when the brand isn't advertising) and project-wide totals. Offset-paginated. adCount is ads we scraped in AI answers, not ad-platform impressions. `days` defaults to 30, max 365.
# List AI-ad creatives
Source: https://docs.searchable.com/api-reference/ads/list-ai-ad-creatives
/api-reference/openapi.json get /api/mcp/projects/{projectId}/ads/creatives
Individual ad creatives (deduped sponsored ad variations) surfaced in AI answers — advertiser, headline, body, image, landing URL, how many scraped responses each appeared in, the prompts + AI models it ran on, and first/last seen. A capped top-N by appearance count (no offset paging). `days` defaults to 30, max 365.
# Agent API
Source: https://docs.searchable.com/api-reference/agent-api
Programmatic access to the Searchable agent
Searchable's conversational agent — the same one behind the in-app chat — is available programmatically for approved customers on a case-by-case basis. This isn't part of the self-serve REST surface documented in this reference and isn't listed in the OpenAPI spec.
If you have a use case for driving the agent directly from your own application or workflow, contact **[support@searchable.com](mailto:support@searchable.com)** with:
* Your workspace and the project(s) involved
* What you're trying to build
* Expected request volume
We'll follow up to scope access and any usage terms.
The self-serve REST endpoints — visibility, sources, sentiment, traffic, audits, reports, and more
— are documented in the rest of this reference and available today with a standard `sea_` API key.
# List raw AI responses for a prompt
Source: https://docs.searchable.com/api-reference/answers/list-raw-ai-responses-for-a-prompt
/api-reference/openapi.json get /api/mcp/projects/{projectId}/prompts/{promptId}/responses
Raw, per-response AI-answer data for one prompt (Profound-parity) — platform, response date, response text, brand/competitor mentions, and citations, one entry per AI response. text is hard-truncated at 2000 characters; truncated flags the cut. Paginated: limit (default 10, max 50) + offset. Returns 404 if promptId doesn't exist or belongs to a different project. `days` defaults to 30, max 365.
# Get an article
Source: https://docs.searchable.com/api-reference/articles/get-an-article
/api-reference/openapi.json get /api/mcp/articles/{articleId}
Full article content + SEO metadata. Checks content_pieces (v2) first, falls back to legacy articles.
# List articles
Source: https://docs.searchable.com/api-reference/articles/list-articles
/api-reference/openapi.json get /api/mcp/projects/{projectId}/articles
List content for a project — merges content_pieces (v2) and legacy articles. `status` defaults to `all` (excludes archived). `limit` defaults to 50, max 100.
# Get page audits
Source: https://docs.searchable.com/api-reference/audits-&-issues/get-page-audits
/api-reference/openapi.json get /api/mcp/projects/{projectId}/audits
Latest page audit per page (SEO + AEO scores) plus summary.lastCompletedAt. Pass includeIssues=true to nest each page's open issues.
# Get page audits (v1 alias)
Source: https://docs.searchable.com/api-reference/audits-&-issues/get-page-audits-v1-alias
/api-reference/openapi.json get /api/v1/projects/{projectId}/audits
Identical contract to `GET /api/mcp/projects/{projectId}/audits` — latest site audit per page + project-level lastCompletedAt. Pass ?includeIssues=true to nest each page's open issues. Requires the `read` scope.
# List monitored pages
Source: https://docs.searchable.com/api-reference/audits-&-issues/list-monitored-pages
/api-reference/openapi.json get /api/mcp/projects/{projectId}/pages
Monitored pages with issue counts.
# List site issues
Source: https://docs.searchable.com/api-reference/audits-&-issues/list-site-issues
/api-reference/openapi.json get /api/mcp/projects/{projectId}/issues
Site issues grouped by severity.
# Refresh the project's sitemap
Source: https://docs.searchable.com/api-reference/audits-&-issues/refresh-the-projects-sitemap
/api-reference/openapi.json post /api/mcp/projects/{projectId}/sitemap/refresh
Re-sync the project's configured sitemap — re-discovers the sitemap and reconciles monitored pages (add/update/remove) + HTTP statuses in the background; returns the coordinator job id. Read the resulting pages on GET /pages. Action endpoint — requires the write scope, enforces runnable-state, and blocks pitch projects. Supports `Idempotency-Key` replay.
# Trigger a site audit
Source: https://docs.searchable.com/api-reference/audits-&-issues/trigger-a-site-audit
/api-reference/openapi.json post /api/mcp/projects/{projectId}/audits
Trigger a site audit (technical + AEO) for the project's pages and return the orchestrator job id; results land on GET /audits. Audits every tracked page by default, or the optional pageIds. Always audits the project's own verified domain. Action endpoint — enforces runnable-state, blocks pitch projects, and consumes the monthly audit quota. Requires the `write` scope. Supports `Idempotency-Key` replay.
# Get brand profile
Source: https://docs.searchable.com/api-reference/brand/get-brand-profile
/api-reference/openapi.json get /api/mcp/projects/{projectId}/brand-profile
The project's brand profile: the knowledge-base profile (positioning, category, topics, connected entities) plus the AI-observed brand facts, optionally filtered by verification status and platform.
# Get domain authority
Source: https://docs.searchable.com/api-reference/brand/get-domain-authority
/api-reference/openapi.json get /api/mcp/projects/{projectId}/domain-authority
The project domain's authority: the latest snapshot plus its history over the requested window.
# Get a competitor
Source: https://docs.searchable.com/api-reference/competitors/get-a-competitor
/api-reference/openapi.json get /api/mcp/projects/{projectId}/competitors/{competitorId}
Full detail for one tracked competitor — the list-view fields plus a per-day history[] and up to 10 recent topPrompts[] it was mentioned in. Two distinct citation metrics: citations (top level) counts every citation on responses that mention the competitor, whatever domain it points at; history[].domainCitations counts citations whose URL is on the competitor's own domain. Returns 404 if competitorId doesn't exist or belongs to a different project. `days` defaults to 30, max 365.
# List competitors
Source: https://docs.searchable.com/api-reference/competitors/list-competitors
/api-reference/openapi.json get /api/mcp/projects/{projectId}/competitors
The project's real/tracked competitors (rows in the competitors table) with share of voice, sentiment score, and all-time mention counts. Paginated. sov/sentimentScore are windowed by days and honor the platform/topicId/unbranded/branded/country/locationId filters; mentions is always all-time and ignores days + all filters (mirrors the in-app Competitors list); visibilityScore and citations are null in the list view — see the detail endpoint for those. `days` defaults to 30, max 365. `limit` defaults to 20, max 100.
# Get GA4 AI-referral visitors
Source: https://docs.searchable.com/api-reference/ga4/get-ga4-ai-referral-visitors
/api-reference/openapi.json get /api/mcp/projects/{projectId}/ga4/ai-referrals
Per-LLM-host AI Source Visitors from GA4 (ChatGPT, Copilot, Gemini, Perplexity, DeepSeek, …): weekly visitor series + week-over-week delta + total. Use this for AI-referral attribution. `weeks` defaults to 12, max 52. Returns 409 ga4_not_connected if no GA4 property is linked.
# Get GA4 top pages
Source: https://docs.searchable.com/api-reference/ga4/get-ga4-top-pages
/api-reference/openapi.json get /api/mcp/projects/{projectId}/ga4/top-pages
GA4 top landing pages by sessions. `weeks` defaults to 12, max 52; `limit` defaults to 20, max 100. Returns 409 ga4_not_connected if no GA4 property is linked.
# Get GA4 traffic sources
Source: https://docs.searchable.com/api-reference/ga4/get-ga4-traffic-sources
/api-reference/openapi.json get /api/mcp/projects/{projectId}/ga4/traffic-sources
GA4 traffic sources by channel group + source. `weeks` defaults to 12, max 52; `limit` defaults to 20, max 100. Returns 409 ga4_not_connected if no GA4 property is linked.
# Get GA4 traffic trend
Source: https://docs.searchable.com/api-reference/ga4/get-ga4-traffic-trend
/api-reference/openapi.json get /api/mcp/projects/{projectId}/ga4/traffic-trend
GA4 daily traffic trend (users, sessions, pageviews) with totals. `weeks` defaults to 12, max 52. Returns 409 ga4_not_connected if no GA4 property is linked.
# Get GSC overview
Source: https://docs.searchable.com/api-reference/gsc/get-gsc-overview
/api-reference/openapi.json get /api/mcp/projects/{projectId}/gsc/overview
Live Google Search Console overview for the project's linked site — total clicks, impressions, CTR, average position for the window, plus an optional previous-period comparison with per-metric deltas. Data lags ~3 days (Google withholds the most recent days). Returns 409 gsc_not_connected if no site is linked.
# Get GSC performance by country
Source: https://docs.searchable.com/api-reference/gsc/get-gsc-performance-by-country
/api-reference/openapi.json get /api/mcp/projects/{projectId}/gsc/countries
Live GSC performance grouped by country (clicks, impressions, CTR, average position). `limit` defaults to 100, max 250. Returns 409 gsc_not_connected if no site is linked.
# Get GSC performance by device
Source: https://docs.searchable.com/api-reference/gsc/get-gsc-performance-by-device
/api-reference/openapi.json get /api/mcp/projects/{projectId}/gsc/devices
Live GSC performance grouped by device (desktop, mobile, tablet). Returns 409 gsc_not_connected if no site is linked.
# Get GSC performance trend
Source: https://docs.searchable.com/api-reference/gsc/get-gsc-performance-trend
/api-reference/openapi.json get /api/mcp/projects/{projectId}/gsc/performance-trend
Live GSC daily performance trend (clicks, impressions, CTR, average position per day) with window totals. Returns 409 gsc_not_connected if no site is linked.
# Get GSC query distribution by position
Source: https://docs.searchable.com/api-reference/gsc/get-gsc-query-distribution-by-position
/api-reference/openapi.json get /api/mcp/projects/{projectId}/gsc/position-buckets
Live GSC query distribution by ranking bucket (1-3, 4-10, 11-20, 20+) with clicks + impressions per bucket. Returns 409 gsc_not_connected if no site is linked.
# Get GSC quick-win queries
Source: https://docs.searchable.com/api-reference/gsc/get-gsc-quick-win-queries
/api-reference/openapi.json get /api/mcp/projects/{projectId}/gsc/opportunities
Live GSC quick-win queries — ranking positions 4-15 with high impressions and low CTR, highest-impressions first. Title/snippet optimization candidates. `limit` defaults to 20, max 100. Returns 409 gsc_not_connected if no site is linked.
# Get GSC top pages
Source: https://docs.searchable.com/api-reference/gsc/get-gsc-top-pages
/api-reference/openapi.json get /api/mcp/projects/{projectId}/gsc/top-pages
Live GSC top pages (page URL, clicks, impressions, CTR, average position), highest-clicks first. `limit` defaults to 25, max 250. Returns 409 gsc_not_connected if no site is linked.
# Get GSC top queries
Source: https://docs.searchable.com/api-reference/gsc/get-gsc-top-queries
/api-reference/openapi.json get /api/mcp/projects/{projectId}/gsc/top-queries
Live GSC top search queries (query, clicks, impressions, CTR, average position), highest-clicks first. `limit` defaults to 25, max 250. Returns 409 gsc_not_connected if no site is linked.
# Getting Started
Source: https://docs.searchable.com/api-reference/introduction
Authentication, rate limits, idempotency, pagination, and errors for the Searchable REST API
## Overview
The Searchable REST API (`/api/mcp/*` and `/api/v1/projects/{projectId}/audits`) exposes the same AI-visibility, sources, sentiment, traffic, and content data available in the Searchable dashboard and [MCP server](/integrations/mcp), over plain HTTP with a bearer API key. It's a **read-mostly** surface — every endpoint below is a GET except the three mutating POSTs (`/reports`, `/audits`, `/sitemap/refresh`).
Every endpoint in the left sidebar is interactive — send a real request from the browser using your own API key.
Narrative walkthroughs + curl/JavaScript examples per data area.
Every error `code` this API returns, and how to fix it.
## Base URL
```
https://app.searchable.com
```
Every path in this reference (e.g. `/api/mcp/projects`) is relative to that base URL.
## Authentication
Create an API key in **Settings → Workspace → Integrations** in your Searchable dashboard. Keys start with `sea_` and are shown only once — store it securely. API access requires a paid Searchable plan; keys can't be created on the Free plan.
Send it as a bearer token on every request:
```
Authorization: Bearer sea_your_key_here
```
This REST surface authenticates with a static `sea_` API key only. The MCP server additionally
supports an OAuth 2.1 login flow for interactive AI clients — see [MCP
integration](/integrations/mcp) if you're connecting Claude, Cursor, or another MCP client instead
of calling REST directly.
### Scopes
Each key carries one or more scopes. Scopes are independent grants, not tiers — `write` does **not** implicitly include `read`:
| Scope | Grants |
| ------- | ------------------------------------------------------------------------------------- |
| `read` | GET endpoints — visibility, sources, sentiment, traffic, content, audits, … |
| `write` | The three action endpoints (`POST /reports`, `POST /audits`, `POST /sitemap/refresh`) |
| `admin` | Every `read` and `write` endpoint |
A key that only calls GET endpoints needs `read`. A key that also needs the three action endpoints needs `write` requested alongside `read` (or `admin`, which covers both). A key missing the required scope gets `403 { code: "missing_scope" }` — see [missing\_scope](/api/errors#missing-scope).
### Project binding
A key can optionally be **bound to a single project** at creation time. A project-bound key can only ever act on that one project — even a request for a project its owning user can otherwise access in the dashboard returns `404 { code: "not_found" }`, indistinguishable from a project that doesn't exist. Leave a key unbound to use it across every project you can access. Bind a key when handing it to a single-tenant integration; leave it unbound for an integration that manages multiple projects.
## Pagination
Two conventions appear across this API, depending on the endpoint:
**Offset pagination** (`limit` + `offset`) — the standard shape for most list endpoints:
```json theme={null}
{
"limit": 20,
"offset": 0,
"returnedCount": 20,
"totalCount": 143,
"hasMore": true,
"nextOffset": 20
}
```
Pass `nextOffset` as the next request's `offset` until `hasMore` is `false`. `totalCount` is occasionally `null` on endpoints where an exact cross-partition total isn't cheap to compute (e.g. `GET /traffic/bots`) — `hasMore`/`nextOffset` still work correctly in that case.
Every offset-paginated endpoint — including `GET /issues`, `GET /opportunities`, and `GET /competitors` — now returns this full block (`hasMore` + `nextOffset` included), so one pagination loop works across the whole API. `GET /competitors` additionally keeps its legacy `total` alias inside `pagination` and its top-level `totalCount`, for backward compatibility.
**Cursor pagination** (`cursor` + `nextCursor`) — used by the Sources domain's URL-listing endpoints (`GET /sources/domains/{domain}/urls`, `GET /sources/urls`), which read from a keyset-ordered store:
```json theme={null}
{ "urls": [/* … */], "totalUrls": 812, "nextCursor": "eyJvZmZzZXQiOjIwfQ", "hasMore": true }
```
Pass the previous response's `nextCursor` as the next request's `cursor`. Omit `cursor` for the first page. Treat the cursor as opaque — don't parse or construct it.
`limit` defaults vary by endpoint (typically 20-50). The big list endpoints — cited domains, cited URLs, prompts, opportunities — accept up to **1,000 rows per page** (issues up to 5,000); values above an endpoint's cap are clamped, never rejected. See each operation's description in the sidebar.
## CSV export
The five biggest list endpoints — `GET /sources/domains`, `GET /sources/urls`, `GET /prompts`, `GET /issues`, `GET /opportunities` — accept `?format=csv` and return the operation's main row set as a downloadable **UTF-8 CSV** (RFC 4180, BOM-prefixed so Excel handles non-ASCII, and spreadsheet-formula-hardened) instead of the JSON envelope:
```bash theme={null}
curl -H "Authorization: Bearer $SEARCHABLE_API_KEY" \
"https://app.searchable.com/api/mcp/projects/PROJECT_ID/sources/urls?limit=1000&format=csv" \
-o cited-urls.csv
```
Pagination parameters apply unchanged — export beyond one page by walking `offset`. Nested JSON fields serialize as minified JSON inside their cell.
## Rate limiting
Every API key is limited to **600 requests/minute** across this REST surface (`/api/mcp/*`, `/api/v1/*`, and the Looker Studio connector — MCP *tool calls* have their own separate concurrency limits, not this budget). Every response carries rate-limit headers, whether it succeeds or errors:
```
RateLimit: "default";r=598;t=42
RateLimit-Policy: "default";q=600;w=60
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 598
X-RateLimit-Reset: 1755000042
```
`RateLimit`/`RateLimit-Policy` follow the [IETF rate-limit header draft](https://www.ietf.org/archive/id/draft-ietf-httpapi-ratelimit-headers-08.html) (`r` = remaining, `t` = seconds until reset, `q` = quota, `w` = window in seconds). `X-RateLimit-*` is kept alongside for clients that read the older convention.
The limiter fails open: if its backing store is briefly unavailable, requests are **allowed** and the rate-limit headers are simply omitted from that response — don't hard-require the headers in client code.
Exceeding the limit returns `429` with a `Retry-After` header (seconds) and a `rate_limited` problem+json body.
## Idempotency
The three mutating POST endpoints — `POST /reports`, `POST /audits`, and `POST /sitemap/refresh` — accept an `Idempotency-Key` header. Send the same key on a retry (after a timeout or a dropped connection) and the API replays the original response instead of repeating the side effect:
```javascript theme={null}
const idempotencyKey = crypto.randomUUID();
const res = await fetch("https://app.searchable.com/api/mcp/projects/PROJECT_ID/reports", {
method: "POST",
headers: {
Authorization: "Bearer sea_YOUR_KEY",
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey,
},
body: JSON.stringify({ reportType: "sentiment" }),
});
// A retry with the SAME idempotencyKey returns the same body and adds:
// X-Idempotent-Replay: true
```
Notes:
* Keys are scoped per API key and held for **24 hours**.
* Only a **successful (2xx)** response is stored — a failed attempt (4xx/5xx) is never replayed; retrying after a real failure with the same key simply runs the request again.
* Two **concurrent** requests with the same key never both execute: the second gets `409 { code: "idempotency_in_flight" }` with `Retry-After: 5` while the first is still running.
* A stored response body over 100KB isn't cached — the request still runs normally, and the response carries `X-Idempotent-Skipped: body-too-large` instead of `X-Idempotent-Replay`.
* No `Idempotency-Key` header — the request behaves exactly as before. Fully opt-in.
## Errors
Every non-2xx response is [`application/problem+json`](https://www.rfc-editor.org/rfc/rfc9457) — a machine-readable envelope that additively extends the API's original `{ error: "..." }` shape, so existing integrations that only read `error` keep working unmodified:
```json theme={null}
{
"type": "https://docs.searchable.com/api/errors#not_found",
"title": "Not Found",
"status": 404,
"code": "not_found",
"error": "Project not found or access denied",
"message": "Project not found or access denied",
"requestId": "b3f1c2a0-4e9d-4a11-9c3a-8e2f6d1a7c55"
}
```
`code` is the field to branch on — it's stable across releases. Full catalog, per-code remediation, and additive fields (`requiresUpgrade`, `retryable`, `current`/`limit`, …): **[API Error Reference](/api/errors)**.
Beyond the statuses listed per operation, any endpoint may also return a generic `500` or `502` problem+json with `code: "internal_error"` on an unexpected internal failure (the `502` variant carries `retryable: true`) — treat both as transient and retry with exponential backoff.
Every response — success or error — also carries `X-Request-Id`. Include it when contacting **[support@searchable.com](mailto:support@searchable.com)** about a specific request.
## Typed clients
There's no official SDK — the OpenAPI spec **is** the contract. Call the API directly with `fetch`/`curl`/your HTTP client of choice, or generate TypeScript types straight from the spec with the MIT-licensed [`openapi-typescript`](https://openapi-ts.dev):
```bash theme={null}
npx openapi-typescript https://docs.searchable.com/api-reference/openapi.json -o searchable-api.d.ts
```
That produces a `paths` / `components` type tree covering every endpoint and schema on this page — pair it with a typed `fetch` wrapper (e.g. [`openapi-fetch`](https://openapi-ts.dev/openapi-fetch/)) for end-to-end type safety with no generated SDK to maintain. An official SDK isn't planned unless customer demand shows up.
## Next steps
Programmatic access to the Searchable agent, for approved customers.
What's new on this API, and the deprecation policy.
# List opportunities
Source: https://docs.searchable.com/api-reference/opportunities/list-opportunities
/api-reference/openapi.json get /api/mcp/projects/{projectId}/opportunities
Actionable opportunities Searchable surfaced for the project — prioritized fix/write/audit suggestions derived from visibility, sentiment, sources, traffic, prompts, site health, and articles. Read-only. Defaults to active opportunities (pass status or includeResolved=true to widen, source/impact to narrow); returns them in the product's priority order plus global stats. Regular-project feature — pitch projects are rejected (403 pitch_not_supported).
# Get a project
Source: https://docs.searchable.com/api-reference/projects/get-a-project
/api-reference/openapi.json get /api/mcp/projects/{projectId}
Get a single project by id.
# List projects
Source: https://docs.searchable.com/api-reference/projects/list-projects
/api-reference/openapi.json get /api/mcp/projects
List all projects the API key can reach — every workspace-accessible project (owner, member, or viewer fallback access), or just the key's bound project if it's project-scoped.
# Get prompt catalog
Source: https://docs.searchable.com/api-reference/prompts/get-prompt-catalog
/api-reference/openapi.json get /api/mcp/projects/{projectId}/prompts
The project's prompt catalog: tracked (default), untracked, AI-suggested, or all prompts, with their configuration and a summary count of each status. Paginated.
# Get query fanout
Source: https://docs.searchable.com/api-reference/query-fanout/get-query-fanout
/api-reference/openapi.json get /api/mcp/projects/{projectId}/query-fanout
Query fanout — the sub-queries AI models generate when answering tracked prompts. Returns the most frequent fanout queries, per-prompt fanout counts, and a per-model breakdown. Paginated: limit/offset page the per-prompt list; topQueriesLimit bounds the top-N queries. Pass unbranded=true or branded=true to filter by prompt brand state. `days` defaults to 30, max 180. `limit` defaults to 50, max 50.
# Get query fanout for a prompt
Source: https://docs.searchable.com/api-reference/query-fanout/get-query-fanout-for-a-prompt
/api-reference/openapi.json get /api/mcp/projects/{projectId}/query-fanout/{promptId}
Detailed query fanout for a single prompt — every sub-query AI models generated for it, deduped with per-query frequency, the models that issued it, and the query type (initial_search | model_query). `days` defaults to 30, max 180.
# Generate a shareable report
Source: https://docs.searchable.com/api-reference/reports/generate-a-shareable-report
/api-reference/openapi.json post /api/mcp/projects/{projectId}/reports
Generate and publish a shareable report; returns { shareToken, shareUrl }. Set whiteLabel=true (requires a white-label-entitled plan) to apply workspace branding. Requires the `write` scope. Supports `Idempotency-Key` replay.
# List shared reports
Source: https://docs.searchable.com/api-reference/reports/list-shared-reports
/api-reference/openapi.json get /api/mcp/projects/{projectId}/reports
List previously shared reports for the project, newest first — { reports: [{id, reportType, title, status, shareUrl, createdAt}], pagination }. Only currently-live, published reports are listed (a report saved as a draft, or later unshared, won't appear). Paginated with limit/offset. `limit` defaults to 20, max 100.
# Get competitor sentiment comparison
Source: https://docs.searchable.com/api-reference/sentiment/get-competitor-sentiment-comparison
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sentiment/competitors
Head-to-head sentiment comparison of the brand vs competitors — sentiment score and positive/neutral/negative share per entity. Pass unbranded=true or branded=true to filter by prompt brand state. `days` defaults to 30, max 365. `limit` defaults to 10, max 50.
# Get sentiment history
Source: https://docs.searchable.com/api-reference/sentiment/get-sentiment-history
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sentiment/history
Brand sentiment trend over time — per-day sentiment score and positive/neutral/negative counts, with an improving/declining/stable trend. Pass unbranded=true or branded=true to filter by prompt brand state. `days` defaults to 90, max 365.
# Get sentiment summary
Source: https://docs.searchable.com/api-reference/sentiment/get-sentiment-summary
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sentiment
Brand sentiment summary + per-platform distribution (positive/neutral/negative share, sentiment score). Pass unbranded=true or branded=true to filter by prompt brand state. `days` defaults to 30, max 365.
# Get share of voice
Source: https://docs.searchable.com/api-reference/share-of-voice/get-share-of-voice
/api-reference/openapi.json get /api/mcp/projects/{projectId}/share-of-voice
Brand vs competitor share of voice — mention-share percentage, rank among all tracked entities, and day-over-day (today vs yesterday) point change per entity. mentions/citations are always null here (not computed by the backing service, and not shown by the in-app view either) — use /competitors for those. Pass unbranded=true or branded=true to restrict by prompt brand state. `days` defaults to 30, max 365.
# Get share of voice history
Source: https://docs.searchable.com/api-reference/share-of-voice/get-share-of-voice-history
/api-reference/openapi.json get /api/mcp/projects/{projectId}/share-of-voice/history
Daily share-of-voice time series for the brand plus its top competitors (competitor set discovered from the same ranking /share-of-voice uses). `days` defaults to 30, max 365.
# Get shopping activation timeseries
Source: https://docs.searchable.com/api-reference/shopping/get-shopping-activation-timeseries
/api-reference/openapi.json get /api/mcp/projects/{projectId}/shopping/timeseries
Daily shopping-activation trend — activation rate, response/product counts, and brand visibility per day. `days` defaults to 30, max 365.
# Get shopping product detail
Source: https://docs.searchable.com/api-reference/shopping/get-shopping-product-detail
/api-reference/openapi.json get /api/mcp/projects/{projectId}/shopping/products/{productId}
Full detail for one product — occurrences, vendor/pricing rows, a real per-platform breakdown, and up to 50 recent responses that surfaced it. Requires a plan with Shopping Analytics (Scale or higher). Returns 404 if not found in the window. `days` defaults to 30, max 365.
# Get shopping visibility summary
Source: https://docs.searchable.com/api-reference/shopping/get-shopping-visibility-summary
/api-reference/openapi.json get /api/mcp/projects/{projectId}/shopping
AI shopping/product visibility (Peec-parity) — top products surfaced in AI shopping/product-carousel responses, ranked by mention volume, plus an activation-rate summary. Returns available:false (200, not an error) when the project has no shopping data yet. Returns 403 requiresUpgrade:true if the workspace's plan doesn't include Shopping Analytics (Scale+) and there is data to fetch. `days` defaults to 30, max 365.
# Get per-URL metrics rollup
Source: https://docs.searchable.com/api-reference/site-health/get-per-url-metrics-rollup
/api-reference/openapi.json get /api/mcp/projects/{projectId}/pages/metrics
One page's three AI series joined in a single call, each as daily buckets: AI-answer citations of the URL, AI-referral sessions landing on it (by platform), and AI-crawler hits fetching it (by bot). `url` is a full URL or a bare path (resolved against the project's domain). The two traffic series degrade to `available: false` when the LLM Analytics integration isn't connected; citations always answer. Default window 90 days (max 365).
# Get a cited domain's detail
Source: https://docs.searchable.com/api-reference/sources/get-a-cited-domains-detail
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/domains/{domain}
Full detail for a single cited source domain — citation share, trend, top prompts, topics, platforms, and content-type breakdown.
# Get a cited page's cached content
Source: https://docs.searchable.com/api-reference/sources/get-a-cited-pages-cached-content
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/urls/{url}/content
Cached scraped markdown and entity mentions (brand/competitor) for a cited page. `{url}` must be percent-encoded. Returns 404 if the URL has not been cited in the project's data window.
# Get a cited URL's detail
Source: https://docs.searchable.com/api-reference/sources/get-a-cited-urls-detail
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/urls/{url}
Citation analytics for a single cited URL — total citations, prompts, mentions, and models that cite it. `{url}` must be percent-encoded. Pass unbranded=true to restrict to non-branded prompts. Returns 404 if the URL has not been cited in the project's data window. `days` defaults to 30.
# Get cited article-type breakdown
Source: https://docs.searchable.com/api-reference/sources/get-cited-article-type-breakdown
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/article-types
Article/content-type breakdown by URL count and citation volume. `days` defaults to 30.
# Get cited content-type distribution
Source: https://docs.searchable.com/api-reference/sources/get-cited-content-type-distribution
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/content-types
Content-type distribution of cited sources (Blog, Product page, How-to, etc.) with citation rates and per-competitor breakdowns. `days` defaults to 30.
# Get cited-source trend
Source: https://docs.searchable.com/api-reference/sources/get-cited-source-trend
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/trend
Citation trend over time for source domains. group='brand' → brand's own cited sources; 'competitors' → competitor cited sources; 'top-domains' (default) → top cited domains overall. Pass unbranded=true to restrict to non-branded prompts. `days` defaults to 30.
# Get cited source-type summary
Source: https://docs.searchable.com/api-reference/sources/get-cited-source-type-summary
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/source-types
Source-type summary (editorial, social, forum, review, institutional, etc.) showing citation counts and share per type. `days` defaults to 30.
# List a domain's cited URLs
Source: https://docs.searchable.com/api-reference/sources/list-a-domains-cited-urls
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/domains/{domain}/urls
Cited URLs for a specific domain, with titles and content types. Cursor-paginated. `days` defaults to 30.
# List AI responses that cited a domain
Source: https://docs.searchable.com/api-reference/sources/list-ai-responses-that-cited-a-domain
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/domains/{domain}/responses
AI responses that cited a specific domain, with the originating prompt, platform, and cited URL. Optionally filter to a specific URL. `days` defaults to 30.
# List all cited URLs
Source: https://docs.searchable.com/api-reference/sources/list-all-cited-urls
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/urls
All cited URLs across a project, with domain, title, content type, and citation counts. Paginated by `offset` (or the legacy `cursor`). `limit` defaults to 20, max 1000 (over-cap values clamp). `days` defaults to 30.
# List cited source domains
Source: https://docs.searchable.com/api-reference/sources/list-cited-source-domains
/api-reference/openapi.json get /api/mcp/projects/{projectId}/sources/domains
Top cited source domains from AI answers — rank, citation counts, usage %, models, and top content types. Paginated and sortable. `days` defaults to 30. `limit` defaults to 20, max 1000 (over-cap values clamp).
# Get prompt rankings within a topic
Source: https://docs.searchable.com/api-reference/topics/get-prompt-rankings-within-a-topic
/api-reference/openapi.json get /api/mcp/projects/{projectId}/topics/prompt-rankings
The prompt-level drill-down into one topic: for every prompt assigned to it, the brand's average rank, its visibility, and the competitors ranking above it. Answers which specific questions a weak topic is losing on. `topicId` is required — rankings are scoped to a single topic.
# Get topic by platform position heatmap
Source: https://docs.searchable.com/api-reference/topics/get-topic-by-platform-position-heatmap
/api-reference/openapi.json get /api/mcp/projects/{projectId}/topics/heatmap
Average brand mention position per topic x AI platform — where the brand is strong on one engine and absent on another. There is deliberately no platform filter: the platform axis is the report.
# Get AI-referral session timeseries
Source: https://docs.searchable.com/api-reference/traffic/get-ai-referral-session-timeseries
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/referrals
First-party AI-referral session timeseries (from the Searchable tracker) — one point per day with a per-platform session breakdown, plus window totals. Returns 409 traffic_not_connected if no source is connected. `days` defaults to 30, max 365.
# Get AI traffic overview
Source: https://docs.searchable.com/api-reference/traffic/get-ai-traffic-overview
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/overview
First-party AI-traffic overview (crawler visits + AI-referral sessions), both broken down by platform, plus the top crawled pages. Returns 409 traffic_not_connected if no tracker/CDN/log source is connected for the project. `days` defaults to 30, max 365.
# Get crawl-to-visit correlation
Source: https://docs.searchable.com/api-reference/traffic/get-crawl-to-visit-correlation
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/correlation
Per page: how often AI crawlers fetched it versus the AI-referred human sessions that followed. Rows are ranked by AI-referral sessions, so a truncated response keeps the pages that actually converted. `limit` defaults to 50, max 200.
# Get human traffic from AI assistants
Source: https://docs.searchable.com/api-reference/traffic/get-human-traffic-from-ai-assistants
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/human
Human sessions that arrived FROM an AI assistant — total sessions and visitors for the window, the AI-referred share of them, and a per-platform split. The conversion half of the funnel that the crawler reports open. Returns 409 traffic_not_connected if no tracker/CDN/log source is connected.
# Get raw request logs
Source: https://docs.searchable.com/api-reference/traffic/get-raw-request-logs
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/logs
The raw request feed with the in-app Logs tab's filters (path, status code, bots-only, host, sitemap-only). Cursor-paginated: pass the previous response's `nextCursor.timestamp` and `nextCursor.event_id` back as `cursorTimestamp` and `cursorEventId`. `limit` defaults to 25, max 100.
`ip_address` and `user_agent` are deliberately not returned — the IP is personal data with no analytical value once `country` is present, and the user-agent is superseded by the resolved `botName` / `botVendor`.
# Get sitemap crawl coverage
Source: https://docs.searchable.com/api-reference/traffic/get-sitemap-crawl-coverage
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/sitemap-coverage
How AI crawlers consume the site's sitemap: per bot, how many times it fetched the sitemap and how often, how many sitemap-listed pages it went on to discover, and the median lag from a page appearing in the sitemap to its first crawl. Use it to answer whether newly published pages are actually reaching AI crawlers. Returns 409 traffic_not_connected if no tracker/CDN/log source is connected.
# Get top AI-referral pages for a platform
Source: https://docs.searchable.com/api-reference/traffic/get-top-ai-referral-pages-for-a-platform
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/top-cited-pages
Top pages driving AI-referral traffic for one platform. `platform` is required (one of openai, anthropic, google, perplexity, microsoft) — 400 without one. Returns 409 traffic_not_connected if no source is connected. `days` defaults to 30, max 365.
# Get traffic attribution
Source: https://docs.searchable.com/api-reference/traffic/get-traffic-attribution
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/attribution
Traffic attribution by UTM tuple (source / medium / campaign) plus referrer domain and bot category, ranked by request count. `limit` defaults to 50, max 200.
# List AI-crawler activity by page
Source: https://docs.searchable.com/api-reference/traffic/list-ai-crawler-activity-by-page
/api-reference/openapi.json get /api/mcp/projects/{projectId}/traffic/bots
Per-page AI-crawler activity — each item is a page with total crawls and a per-platform breakdown (or one platform's count when filtered). Paginated. Returns 409 traffic_not_connected if no source is connected. `days` defaults to 30, max 365.
# Get per-prompt visibility
Source: https://docs.searchable.com/api-reference/visibility/get-per-prompt-visibility
/api-reference/openapi.json get /api/mcp/projects/{projectId}/visibility/prompts
Per-prompt visibility breakdown. Paginated — the response `pagination` block returns `hasMore` + `nextOffset`; pass `offset` to page through all prompts. `days` defaults to 30, max 180. `limit` defaults to 500, max 5000.
# Get per-topic visibility
Source: https://docs.searchable.com/api-reference/visibility/get-per-topic-visibility
/api-reference/openapi.json get /api/mcp/projects/{projectId}/visibility/topics
Topic-level visibility metrics. Pass unbranded=true or branded=true to restrict every metric by prompt brand state. `days` defaults to 30.
# Get visibility by AI platform
Source: https://docs.searchable.com/api-reference/visibility/get-visibility-by-ai-platform
/api-reference/openapi.json get /api/mcp/projects/{projectId}/visibility/platforms
Visibility broken down by AI platform. The same rows appear inside `GET /visibility` as `platforms[]`; this endpoint returns that breakdown on its own and can narrow to specific platforms. `platform` is comma-separated and resolved through the canonical platform map, so it accepts display names (`ChatGPT`, `AI Overviews`), aliases (`openai`, `microsoft`, `xai`), and raw model ids alike — `platform=chatgpt` matches a stored `chatgpt-4o` without also matching a `copilot-gpt-*` id, which belongs to Copilot. Filter further with `topicId` / `country` / `locationId` (each must be a UUID; a malformed value returns 400 `invalid_argument`), and pass unbranded=true or branded=true to filter by prompt brand state. `days` defaults to 30, max 365.
# Get visibility by location
Source: https://docs.searchable.com/api-reference/visibility/get-visibility-by-location
/api-reference/openapi.json get /api/mcp/projects/{projectId}/visibility/locations
Visibility broken down by tracked location (per-country/city), with share of voice, sentiment, avg position, and the change vs the prior equal-length window. Filter with `country` / `locationId` / `platform` / `topicId`. Pass unbranded=true or branded=true to filter by prompt brand state. Returns all locations when unfiltered. `days` defaults to 30, max 365.
# Get visibility history
Source: https://docs.searchable.com/api-reference/visibility/get-visibility-history
/api-reference/openapi.json get /api/mcp/projects/{projectId}/visibility/history
Visibility time-series data, one point per report. Pass unbranded=true or branded=true to compute the per-report score and stats by prompt brand state. `days` defaults to 90, max 365.
# Get visibility summary
Source: https://docs.searchable.com/api-reference/visibility/get-visibility-summary
/api-reference/openapi.json get /api/mcp/projects/{projectId}/visibility
AI visibility score + platform breakdown. Pass unbranded=true or branded=true to restrict every metric (score, mentions, citations) by prompt brand state. `days` defaults to 30, max 365.
# API Error Reference
Source: https://docs.searchable.com/api/errors
Every error code the Searchable REST API returns, what it means, and how to fix it
## Overview
Every error response from the REST API (`/api/mcp/*`, `/api/v1/*`, and the Looker Studio connector) is shaped as [`application/problem+json`](https://www.rfc-editor.org/rfc/rfc9457) — a machine-readable envelope that additively extends the API's original `{ error: "..." }` shape. Existing integrations that only read `error` keep working unmodified.
```json theme={null}
{
"type": "https://docs.searchable.com/api/errors#not_found",
"title": "Not Found",
"status": 404,
"code": "not_found",
"error": "Project not found or access denied",
"message": "Project not found or access denied",
"howToFix": "...",
"requestId": "b3f1c2a0-4e9d-4a11-9c3a-8e2f6d1a7c55"
}
```
| Field | Meaning |
| ----------- | --------------------------------------------------------------------------------------------------- |
| `type` | A URL identifying the error kind — always this page, anchored to `code` |
| `title` | Human-readable summary of `code` |
| `status` | The HTTP status code (matches the response status) |
| `code` | Machine-readable error code — stable, safe to branch on |
| `error` | **Legacy compat key.** Always equal to `message`. Existing integrations that read this keep working |
| `message` | Human-readable error message (identical to `error`) |
| `howToFix` | Present on actionable errors — a concrete next step |
| `requestId` | The request's id. Include this when contacting support |
Some errors carry additional fields beyond this base shape (e.g. `requiresUpgrade`, `retryable`, `current`/`limit` on a quota error) — those are documented per-code below and are additive, never replacing the fields above.
## Quick reference
| Code | Status | Meaning |
| ------------------------------------------------- | ------- | ----------------------------------------------------------------------------- |
| [`unauthorized`](#unauthorized) | 401 | Missing, malformed, revoked, or expired API key |
| [`forbidden`](#forbidden) | 403 | Access denied to the requested resource |
| [`missing_scope`](#missing-scope) | 403 | The API key lacks the required `read`/`write` scope |
| [`plan_upgrade_required`](#plan-upgrade-required) | 403 | The workspace's plan doesn't include this feature |
| [`not_found`](#not-found) | 404 | The resource doesn't exist, or the key can't reach it |
| [`invalid_argument`](#invalid-argument) | 400 | A query parameter, path parameter, or body field is invalid |
| [`invalid_country`](#invalid-country) | 400 | An unrecognized `country` filter value |
| [`no_domain`](#no-domain) | 400 | The project has no verified domain configured |
| [`no_workspace`](#no-workspace) | 400/403 | The project isn't linked to a workspace |
| [`no_pages`](#no-pages) | 400 | No tracked (or matching) pages to audit |
| [`bulk_limit_exceeded`](#bulk-limit-exceeded) | 400 | Too many pages requested for a bulk audit on this plan |
| [`quota_exceeded`](#quota-exceeded) | 403 | A monthly/concurrent usage quota is exhausted |
| [`project_not_runnable`](#project-not-runnable) | 403 | The project is paused or archived — background jobs are blocked |
| [`pitch_not_supported`](#pitch-not-supported) | 403 | The feature isn't available on pitch (scoped) projects |
| [`rate_limited`](#rate-limited) | 429 | Too many requests — per-key REST rate limit, or a per-project concurrency cap |
| [`idempotency_in_flight`](#idempotency-in-flight) | 409 | A request with the same `Idempotency-Key` is still running |
| [`query_timeout`](#query-timeout) | 504 | The query took too long — narrow the request and retry |
| [`gsc_not_connected`](#gsc-not-connected) | 409 | No Google Search Console site linked to the project |
| [`gsc_site_not_linked`](#gsc-site-not-linked) | 404 | The linked GSC site record doesn't match the project |
| [`gsc_access_denied`](#gsc-access-denied) | 403 | Google revoked/denied access — reconnect the account |
| [`ga4_not_connected`](#ga4-not-connected) | 409 | No Google Analytics 4 property linked to the project |
| [`traffic_not_connected`](#traffic-not-connected) | 409 | No crawler-log, CDN, or tracker source connected |
| [`internal_error`](#internal-error) | 500 | An unexpected server error — retry, then contact support |
## Authentication & authorization
### `unauthorized`
**401.** The request has no `Authorization: Bearer sea_...` header, the key doesn't start with `sea_`, or the key is invalid, revoked, or expired.
**Fix:** Check the header is `Authorization: Bearer sea_xxxxx`. Create or rotate the key under **Settings → Workspace → Integrations**.
### `forbidden`
**403.** The authenticated key's user doesn't have access to the requested resource (distinct from a missing scope or a not-found — the resource exists but this key's user isn't a member, or the project is inactive).
**Fix:** Confirm the key's owning user is a member of the workspace that owns the resource.
### `missing_scope`
**403.** The key doesn't carry the scope the endpoint requires. Read endpoints require `read`; write/action endpoints (report generation, triggering an audit, refreshing a sitemap) require `write`. `admin` covers both.
**Fix:** Create a new key with the required scope, or use a key that already has it. See [Scopes](/advanced/api-usage#scopes).
### `plan_upgrade_required`
**403.** The action is gated behind a plan the workspace isn't on (white-label branding, report sharing, Shopping Analytics, Looker Studio integration, query fanout, …). Often carries `requiresUpgrade: true`.
**Fix:** Upgrade the workspace's plan under **Settings → Billing**.
## Not found & validation
### `not_found`
**404.** The resource doesn't exist, or the API key's project binding doesn't allow it to reach the requested project (a project-bound key can never see another project, even one its owning user can access in-app — see [Scopes](/advanced/api-usage#scopes)). Deliberately indistinguishable from "doesn't exist" so existence never leaks to a caller who shouldn't see it.
**Fix:** Double-check the id in the URL. If the key is project-bound, confirm you're calling it for its own project.
### `invalid_argument`
**400.** A query parameter, path parameter, or request body failed validation (e.g. an out-of-range `days`, a malformed date, an invalid enum value, or a body that fails its schema). The response often carries `details` with the field-level breakdown.
**Fix:** Check the parameter/body shape against the endpoint's documented params.
### `invalid_country`
**400.** The `country` filter value isn't a recognized ISO code or name.
**Fix:** Pass a valid ISO 3166-1 country code (e.g. `US`, `GB`) or `locationId` instead.
### `no_domain`
**400.** The project has no verified domain — required before an audit or sitemap sync can run (the audited origin is always derived from the project's own domain, never a caller-supplied URL).
**Fix:** Set the project's domain in the dashboard, then retry.
### `no_workspace`
**400 or 403.** The project isn't linked to a workspace, so plan/feature checks (Looker Studio, audits) have nothing to evaluate against.
**Fix:** This is an account-configuration issue — contact **[support@searchable.com](mailto:support@searchable.com)**.
### `no_pages`
**400.** `POST /audits` was called with no tracked pages and no explicit `pageIds`, or every id in `pageIds` didn't match a page in this project.
**Fix:** Track at least one page first, or pass valid `pageIds` for this project.
### `bulk_limit_exceeded`
**400.** The requested page count for a single `POST /audits` call exceeds the workspace's plan limit. Carries `bulkLimitExceeded: true`, `requested`, and `maxAllowed`.
**Fix:** Pass a smaller `pageIds` list, split the audit into multiple calls, or upgrade the plan.
## Quota & runnability
### `quota_exceeded`
**403.** A monthly or concurrent usage quota (audits, reports, prompts, …) is exhausted. Carries `quotaExceeded: true`, `current`, and `limit`.
**Fix:** Wait for the quota to reset (monthly quotas), reduce concurrent usage, or upgrade the plan.
### `project_not_runnable`
**403.** The project is paused or archived. Background work (audits, sitemap sync, report generation) requires an active, non-archived project.
**Fix:** Resume the project in the dashboard before retrying.
### `pitch_not_supported`
**403.** The endpoint isn't available for pitch (scoped, pre-conversion) projects — opportunities, audits, and sitemap sync are regular-project-only features.
**Fix:** This endpoint only supports regular (non-pitch) projects.
## Rate limiting & timeouts
### `rate_limited`
**429.** Either the per-API-key REST rate limit (600 requests/minute) was exceeded, or — on some endpoints — a per-project concurrency cap was already held by another in-flight request from the same key. The response carries a `Retry-After` header (seconds) and `retryable: true`. See [Rate limiting](/advanced/api-usage#rate-limiting).
**Fix:** Back off for `Retry-After` seconds, then retry. Spread bursts of requests across a longer window rather than firing them all at once.
### `idempotency_in_flight`
**409.** Another request carrying the same `Idempotency-Key` is still executing — the duplicate was refused instead of running the side effect a second time. Carries a `Retry-After` header (5 seconds) and `retryable: true`. See [Idempotency](/advanced/api-usage#idempotency).
**Fix:** Wait `Retry-After` seconds, then retry **with the same key** — once the original completes successfully you'll receive its stored response (`X-Idempotent-Replay: true`); if the original failed, the retry runs fresh.
### `query_timeout`
**504.** The query took longer than the endpoint's timeout budget. Carries `timeout: true` and `retryable: true`.
**Fix:** Narrow the `days` window or add filters (platform, topic, location), then retry.
## Google integrations
### `gsc_not_connected`
**409.** No Google Search Console site is linked to this project.
**Fix:** Connect Google Search Console under **Settings → Integrations**, then retry.
### `gsc_site_not_linked`
**404.** The project has a GSC site reference that doesn't resolve — a narrower variant of "not connected" surfaced by some GSC endpoints.
**Fix:** Reconnect Google Search Console under **Settings → Integrations**.
### `gsc_access_denied`
**403.** Google denied the request — the connected account's token was revoked, permission to the property was removed, or the property was unshared. Distinct from `gsc_not_connected`: the integration was connected, but Google is now rejecting it.
**Fix:** Reconnect the Google account under **Settings → Integrations**.
### `ga4_not_connected`
**409.** No Google Analytics 4 property is linked to this project.
**Fix:** Connect Google Analytics 4 under **Settings → Integrations**, then retry.
## AI Traffic
### `traffic_not_connected`
**409.** No crawler-log, CDN, or Searchable-tracker data source is connected for this project.
**Fix:** Connect a source under **AI Traffic → Setup**.
## Server errors
### `internal_error`
**500.** An unexpected server-side failure. Never leaks internal error text — the message is always a stable, generic description.
**Fix:** Retry with exponential backoff. If it persists, contact **[support@searchable.com](mailto:support@searchable.com)** with the `requestId` from the response body.
## Need more?
Higher rate limits, a code not listed here, or a question about a specific response? Contact **[support@searchable.com](mailto:support@searchable.com)** with the endpoint, `requestId`, and response body.
# Changelog
Source: https://docs.searchable.com/changelog
Updates to the Searchable REST API and MCP server
Everything here is **additive** — no existing call changes shape, and every capability lands on
both the MCP tools and the matching REST endpoints, which share one implementation.
**Absolute date ranges (`from` / `to`).** Previously only Search Console accepted explicit dates;
everything else spoke in relative `days`, so "compare March against June" or "the week of the
launch" could not be expressed. Every windowed read now takes `from` and `to` (inclusive, UTC,
`YYYY-MM-DD` or full ISO): `get_visibility` (all views), `get_share_of_voice`, `get_sentiment`,
`get_topic_analysis`, `get_ai_traffic`, and their REST twins. Both bounds are required together and
are mutually exclusive with `days` — sending both returns `400 invalid_argument` rather than
silently picking one. An over-long `days` is still clamped; an over-long explicit range is
**rejected**, because narrowing a range you spelled out would answer a different question.
**Five new AI Traffic reports** on `get_ai_traffic` (and as REST endpoints under
`/traffic/*`):
| Report | Answers |
| ------------------ | -------------------------------------------------------------------------------- |
| `sitemap_coverage` | Per bot: sitemap fetch cadence, pages discovered, publish-to-crawl lag |
| `human` | Human sessions that arrived from an AI assistant, split by platform |
| `correlation` | Per page, crawls versus the AI-referred sessions that followed |
| `attribution` | Traffic by UTM tuple, referrer, and bot category |
| `logs` | The raw request feed — filter by path, status, bots-only, host; cursor-paginated |
`logs` is row-capped (25 default, 100 max) and **never returns `ip_address` or `user_agent`**: the
IP is personal data with no analytical value once `country` is present, and the user-agent is
superseded by the resolved bot identity. A new `host` parameter narrows any traffic report to
specific hostnames on multi-domain projects.
**New views on the existing families.**
* `get_share_of_voice` gains `group_by="date"` — the daily brand-versus-competitor share series, for "is our share growing".
* `get_topic_analysis` gains `view="prompts"` (per-prompt rank inside one topic, with the competitors outranking you — requires `topicId`) and `view="heatmap"` (average brand position per topic x AI platform). Both are also REST endpoints: `/topics/prompt-rankings` and `/topics/heatmap`.
* `get_visibility` gains `include="industry_ranking"` — the competitive leaderboard attached to the summary.
* Date-series views gain `include="annotations"`: the dated markers (campaign launches, migrations) overlapping the window, so a spike arrives with its explanation.
**Filters.** `list_prompts` (and `GET /prompts`) accept `search` for a case-insensitive substring
match on prompt text — `%` and `_` match literally rather than as wildcards. `topicId` accepts a
comma-separated list on the surfaces whose queries take several (`get_visibility`,
`get_share_of_voice`, `get_sentiment`, `get_topic_analysis`, `get_competitors`,
`get_shopping_visibility`); single-topic surfaces (`list_prompts`, `get_query_fanout`, `get_ads`)
document and accept one id rather than advertising a list they would reject. `list_projects` returns
`dataAvailableFrom` per project — the earliest date with a **completed, scored** visibility report —
so a client can size its windows instead of discovering the horizon through empty results.
**Reading the new reports honestly.** Three contracts are worth knowing before you parse them:
* `report="human"` carries a `summarySource`. Site-wide totals come from the first-party tracker
while the AI figures fall back to GA4 when no tracker is installed; in that split state every
`summary` field and `percentOfTotal` are `null` rather than `0`, and a failed GA4 read arrives as
`aiReferral.sourceError` instead of as zeroes.
* `report="correlation"` joins crawls and AI-referred sessions over the **same window** by path.
That is co-occurrence, not attribution — nothing establishes that a session followed a crawl. Its
`pagesConsidered` is a floor on the page count, with `populationTruncated` flagging when the
upstream per-set cap means pages are missing.
* `include="industry_ranking"` returns the top 25 entities, not the whole field: `hasMore` flags a
longer leaderboard, `brandRankStatus` separates "ranks below the cutoff" from "unranked", and
`totalEntities` is `null` when truncated.
Arguments a view cannot apply are now `invalid_argument` errors rather than silent no-ops — an
`include` on a view that attaches no blocks, `topicId` on the all-topics view, `platform` on the
topic x platform heatmap, an explicit range longer than `group_by=prompt`'s 180-day ceiling, and
half a log cursor. Impossible calendar dates (`2026-02-30`) are rejected instead of rolling into the
next month, and markdown headings name an explicit range instead of relabelling it "last N days".
`logs`, `sitemap_coverage`, and `attribution` require a crawler-log source and return
`traffic_not_connected` for analytics-only projects, rather than an empty `200` that reads as "no
crawler traffic".
**Four reads folded into their family's primary tool.** The visibility trend, the two sentiment side-views, and domain authority are now selector parameters instead of standalone tools:
| Old tool | New call |
| --------------------------- | --------------------------------------------------- |
| `get_visibility_history` | `get_visibility` (`group_by: "date"`) |
| `get_sentiment_history` | `get_sentiment` (`view: "history"`) |
| `get_sentiment_competitors` | `get_sentiment` (`view: "competitors"`) |
| `get_domain_authority` | `get_brand_profile` (`include: "domain_authority"`) |
**The old names still work.** All four stay registered as deprecated stubs with byte-identical payloads, so existing scripts and scheduled jobs are unaffected today. They are scheduled for removal **after 2026-10-15** — the same \~60-day window the removed aliases got. An unsupported combination on the new views (for example `compare` on `view=history`, or a `platform` filter on `group_by=date`) returns `invalid_argument` instead of being silently ignored.
**REST is untouched.** `GET /visibility/history`, `GET /sentiment/history`, `GET /sentiment/competitors`, and `GET /domain-authority` are not deprecated and follow the standard [12-month policy](/changelog#deprecation-policy) as before.
**Leaner tool descriptions.** Tool descriptions across the server were tightened (\~18% smaller) with no behavioral facts removed — every MCP client loads the full tool list into model context each conversation, so this directly cuts per-conversation overhead.
**Period comparison in one call.** `GET /visibility`, `GET /visibility/topics`, `GET /share-of-voice`, and `GET /sentiment` (and the matching MCP tools `get_visibility`, `get_share_of_voice`, `get_sentiment`) accept `compare=previous_period` or `compare=previous_year`. The response gains an additive `comparison` block — the previous window's metrics plus current-minus-previous deltas — so "how did we do vs last month?" no longer needs two calls and client-side math. On `/visibility/topics`, per-topic deltas ride inline on each topic row. On `/share-of-voice`, every competitor row gains `previousSov`/`sovDelta`.
**Per-URL metrics rollup.** New `GET /projects/{projectId}/pages/metrics?url=…` (and the `get_page_metrics` MCP tool): one page's three AI series joined in a single call — citations of the URL in AI answers, AI-referral sessions landing on it (by platform), and AI-crawler hits fetching it (by bot), each as daily buckets. Traffic series degrade to `available: false` when the LLM Analytics integration isn't connected; citations always answer.
**CSV export + bigger pages.** The five biggest list endpoints — cited domains, cited URLs, prompts, issues, opportunities — accept `?format=csv` (RFC 4180, BOM-prefixed, spreadsheet-formula-hardened). Page-size caps rose for bulk pulls: cited domains/URLs and prompts to **1,000** rows per page, opportunities to 1,000; values above a cap clamp instead of erroring.
**Consistent pagination everywhere.** `GET /issues`, `GET /opportunities`, and `GET /competitors` now return the full standard offset block (`hasMore` + `nextOffset` included) — the derive-it-yourself caveats are gone from the docs because they're gone from the API.
**New MCP orientation tools.** `get_current_date` (UTC anchor + pre-computed 7/30/90/365-day window starts, so assistants never do date arithmetic), `whoami` (who this connection is, its read/write scopes, and its visible project roster), and `search_docs` / `read_doc` (full-text search + retrieval over this documentation, served from the app's embedded corpus — assistants can answer "how is the visibility score calculated?" in-chat). Plus two MCP **resources**: `searchable://glossary` and `searchable://glossary/full` — metric and concept definitions with the tools that read each one.
**`responseMentionRate` is the mention metric to use.** It is the percentage (0-100) of AI responses that mention your brand, and it means **the same thing on every endpoint** — added to both `GET /visibility` (`summary.responseMentionRate`) and `GET /visibility/history` (per data point). `GET /visibility/history` data points also now return `responsesWithBrand`, so the rate is auditable from the payload alone.
**Why:** `mentionRate` does not mean the same thing on both endpoints, and never has.
* On `GET /visibility` it is a **share** of responses — bounded 0-100.
* On `GET /visibility/history` it is a **density**: brand mentions ÷ responses × 100. Because one response can mention a brand several times, this routinely reads **above 100%** (a real project reads 393%). That is the value it has always returned, not a recent regression.
`mentionRate` and `overallMentionRate` are therefore **deprecated but unchanged** on `GET /visibility`, `GET /visibility/history`, and `GET /visibility/prompts`. They keep returning exactly what they always have — we do not silently recalculate a shipped field. There is **no removal date**; per the policy below you would get at least 12 months' notice, and this entry starts no clock. If you want the density, it stays derivable as `brandMentions / totalResponses * 100`.
**Migrating:** replace `mentionRate` with `responseMentionRate` on `/visibility` and `/visibility/history`. On `/visibility/prompts`, `mentionRate` / `overallMentionRate` are exact aliases of `visibilityScore` / `overallVisibilityScore` — same value, so switching is a rename with no data change.
**Also new: `GET /visibility/platforms`** — per-AI-platform visibility (the platform counterpart to `/visibility/topics` and `/visibility/locations`). `platform` is comma-separated and accepts display names, aliases, and raw model ids.
**MCP: sign in instead of pasting a key.** The MCP server now supports an OAuth 2.1 login flow (PKCE + Dynamic Client Registration) — connect Claude, Cursor, or another MCP client by signing in and approving access, scoped to exactly the projects and read/write permissions you choose. The `sea_` API-key bearer path still works unchanged for scripts and headless clients. See [MCP integration](/integrations/mcp).
**New data coverage**, in REST and as MCP tools:
* **Share of Voice & Competitors** — brand vs. competitor mention-share ranking, its daily trend, and the full tracked-competitor roster
* **AI Traffic** — first-party AI-crawler visits and AI-referral sessions, sourced from the tracker/CDN pipeline
* **Shopping visibility** — AI shopping/product-carousel appearances
* **Prompt Answers** — raw, per-response AI-answer data (text, mentions, citations) for a single prompt
* **`GET /reports`** — list previously generated shareable reports for a project
**Write actions over MCP** — `generate_report`, `trigger_audit`, and `refresh_sitemap` are now callable as MCP tools (in addition to their existing REST POST endpoints), each gated on the `write` scope and an explicit confirmation.
**Hardened REST responses.** Every response now carries an `X-Request-Id` and standard rate-limit headers (600 requests/minute per API key); errors are RFC 9457 `application/problem+json` with a stable `code` field you can branch on. See the new **[error reference](/api/errors)**. The `POST /reports`, `POST /audits`, and `POST /sitemap/refresh` endpoints additionally accept an `Idempotency-Key` header, so a retry after a timeout or dropped connection never triggers the action twice.
**Clearer "not connected" errors.** Google Search Console, Google Analytics 4, and AI Traffic endpoints now return an actionable `409` with a direct link to the right settings page when the integration isn't connected yet, instead of a generic failure.
**This page, and the interactive [API reference](/api-reference/introduction)** — a full OpenAPI 3.1 spec with a live playground for every endpoint, generated straight from the shipped route contracts.
## Deprecation policy
* **12 months' notice.** We give at least 12 months' notice before removing or changing the behavior of any documented endpoint, parameter, or response field. Adding a new endpoint or an additive response field is not a breaking change and isn't subject to this notice.
* **`Deprecation` / `Sunset` headers.** Once an endpoint is scheduled for removal, its responses carry a `Deprecation` header (the date it was deprecated) and, once a removal date is fixed, a `Sunset` header (the date it stops working), per the [IETF Sunset header convention](https://www.rfc-editor.org/rfc/rfc8594). Nothing on this API is scheduled for removal today, so no `Sunset` header is in play. The `mentionRate` / `overallMentionRate` response fields are marked deprecated in the API reference (see the July 2026 entry above) — they remain fully supported with no removal date, and are superseded by `responseMentionRate`.
* **Versioning posture.** `/api/mcp/*` — despite the name — is the frozen v1 REST contract: stable, versionless-by-default. New capabilities land as new endpoints or new additive fields, never as a breaking change to an existing one. `/api/v1/*` is reserved for surfaces that need independent versioning from that contract (currently just `/api/v1/projects/{projectId}/audits`, which mirrors `GET /api/mcp/projects/{projectId}/audits` exactly).
* A breaking change, if one is ever required, ships as a new endpoint or a new version prefix, announced here first, with the prior version supported through the full notice window.
Questions about an upcoming change? **[support@searchable.com](mailto:support@searchable.com)**.
# Connecting Your First Domain
Source: https://docs.searchable.com/getting-started/creating-your-project
Step-by-step guide to setting up your first domain in Searchable
**On this page:** What is a Domain • Before You Start • Connecting Your Domain • After Domain Setup • Domain Settings • Managing Workspaces • Common Issues • Best Practices
## What is a Domain in Searchable?
In Searchable, a **domain** represents a website you want to monitor and optimize for AI visibility. Each domain (backed by a project in the API) can track multiple pages, run audits, monitor AI mentions, and generate optimized content.
Most users connect **one domain per website** they manage. Under the hood, each domain is stored as a project in the API, but everywhere in the product you'll work with domains.
## Before You Start
Make sure you have:
Your website's primary domain (e.g., `https://yourwebsite.com`)
Access to verify domain ownership (if setting up integrations)
A clear understanding of your industry/niche
Target keywords or topics (optional but recommended)
## Connecting Your Domain
From your dashboard, click the **"Add Domain"** button in the sidebar, or open **Settings** → **Workspace & Domains** and use the domain table actions.
Starter ($100/mo) is designed for a single tracked domain. Professional ($300/mo) supports two concurrent domains, Agency (\$750/mo) expands to five, and Custom plans can be tailored for additional scale.
Fill in the essential details about your website:
**Display name**
* Choose a memorable name for internal reference (optional)
* Example: "Company Blog" or "Main Website"
**Website domain**
* Enter your primary domain
* Format: `yourwebsite.com` (we'll normalize `https://` for you)
* Don't include specific pages or paths
Make sure to use the correct protocol (http\:// or https\://). This affects how we crawl and analyze your site.
**Industry Category**
* Select your primary industry from the dropdown
* Options include: Technology, Healthcare, Finance, E-commerce, Education, and more
* This helps us provide industry-specific recommendations
Customize how Searchable monitors your website:
**Monitoring Frequency**
* All plans include continuous monitoring
* Audit limits vary by plan (see [Plans & Pricing](/getting-started/plans-pricing))
* Starter: 25 pages, Professional: 100 pages, Agency: 500 pages (Custom plans are tailored during onboarding)
**Pages to Monitor**
* Choose "Auto-discover" to let Searchable find important pages
* Or manually add specific URLs to monitor
* You can always add more pages later (within your plan's audit limits)
Start with your most important pages to maximize your monthly audit allocation.
**Target Keywords (Optional)**
* Add 3-5 primary keywords relevant to your business
* These help us track your AI visibility for specific topics
* Example: "CRM software", "project management tool"
Add initial prompts to track your brand mentions across AI platforms:
**Default Prompts**
* Searchable suggests prompts based on your industry
* These track how AI models mention your brand
**Custom Prompts**
* Add industry-specific questions
* Example: "What are the best CRM tools for small businesses?"
* Plan limits: Starter (50), Professional (100), Agency (1,000), Custom (configured with sales)
Start with 5-10 prompts and expand based on what works. Learn more in [Working with Prompts](/using-searchable/working-with-prompts).
Click **"Create Project & Start Crawl"** to begin:
**What Happens Next:**
* Searchable crawls your website (usually takes 2-10 minutes)
* Discovers pages and analyzes site structure
* Runs initial technical and content audits
* Generates your first AI visibility report
You'll receive an email when your initial analysis is complete. Most crawls finish within 5 minutes.
## After Domain Setup
Once your domain is connected, you'll land on the main dashboard where you can:
### View Initial Results
See your overall technical and content quality score (0-100)
Review all pages found during the initial crawl
Identify urgent technical or content problems
Your starting point for brand mention tracking
### Next Actions
1. **Review Discovered Pages**
* Navigate to **Pages** tab
* Mark important pages for priority monitoring
* Remove any pages you don't want to track
2. **Fix Critical Issues**
* Go to **Issues** tab
* Start with critical and high-priority items
* Follow our recommendations for quick wins
3. **Add More Prompts**
* Visit **Prompts** tab
* Add industry-specific questions
* Import prompt templates
4. **Set Up Integrations**
* Connect Google Search Console for keyword data
* Add Google Analytics for traffic insights
## Domain Settings
Access domain settings anytime via **Settings** → **Workspace & Domains** and selecting a domain.
### General Settings
* **Domain name**: Update your domain display name
* **Primary domain**: Change primary domain (requires re-crawl)
* **Industry**: Update industry category
* **Time Zone**: Set your preferred timezone for reporting
### Crawl Settings
* **Crawl Frequency**: How often to audit your site
* **Max Pages**: Limit pages to monitor (based on your plan)
* **Crawl Depth**: How many levels deep to crawl from homepage
* **Excluded Paths**: Skip certain URL patterns (e.g., `/admin/*`)
```yaml Example: Exclude Patterns theme={null}
# Exclude admin pages
/admin/*
/wp-admin/*
# Exclude user-specific pages
/user/*/profile
# Exclude test environments
/staging/*
/test/*
```
### Notification Settings
Configure when and how you receive updates:
* **Email Reports**: Daily, weekly, or monthly summaries
* **Issue Alerts**: Get notified when critical issues are found
* **Visibility Changes**: Track significant changes in AI mentions
* **Audit Completion**: Know when crawls finish
## Managing Multiple Workspaces
If you manage more than one brand, upgrading increases how many domains and seats you can run in parallel:
### Understanding Workspaces
Each workspace can host several domains and teammates:
* **Starter (\$100)**: 1 tracked domain, 1 seat
* **Professional (\$300)**: 2 tracked domains, up to 10 seats
* **Agency (\$750)**: 5 tracked domains, up to 25 seats
* **Custom**: Scaled during contracting
### Switching Workspaces
* Use the workspace selector in the top navigation
* Recently viewed workspaces appear at the top
* Pin favorite workspaces for quick access
### Comparing Domains
* Navigate to **Analytics** and switch between domains using the sidebar domain switcher
* See performance across all domains within a workspace
* Identify which sites need attention
### Team Access
* Invite team members in **Settings** → **Team**
* Seats included: Starter (1), Professional (10), Agency (25), Custom (tailored)
* Set permissions per domain
* Share dashboards and reports
## Common Issues & Solutions
**Possible Causes:**
* Robots.txt blocking our crawler
* Slow server response times
* Large site with many pages
**Solutions:**
* Verify Searchable's crawler is allowed in robots.txt
* Check your site's performance
* Start with fewer pages (within your plan's audit limit) and expand gradually
**Possible Causes:**
* Pages aren't linked from your homepage
* Pages blocked by robots.txt or noindex tags
* Pages behind authentication
**Solutions:**
* Manually add specific URLs in **Pages** → **Add Page**
* Check internal linking structure
* Verify crawl depth settings
You can update your domain in **Settings** → **Workspace & Domains** → **Domain details**. This will trigger a new crawl. Alternatively, delete the domain and create a new one.
Yes! Go to **Settings** → **Workspace & Domains** → **Domain details** and update your industry. This will update our recommendations and prompt suggestions.
Your plan determines your monthly limits:
* **Starter (\$100)**: 25 audits, 50 prompts, 5 articles
* **Professional (\$300)**: 100 audits, 100 prompts, 25 articles
* **Agency (\$750)**: 500 audits, 1,000 prompts, 100 articles
* **Custom**: Tailored allocations and unlimited article generation
Upgrade anytime in **Settings** → **Billing** or contact [support@searchable.com](mailto:support@searchable.com) for Custom provisioning.
## Best Practices
Start with your most important pages rather than crawling everything
Add prompts that your target customers would actually ask
Set up email notifications to stay informed
Review your dashboard weekly to track progress
Connect integrations early for richer data
## Video Tutorial
## Next Steps
Learn to navigate your domain dashboard
Understand what your scores mean
Create effective prompts for tracking
Connect your tools and platforms
# Plans & Pricing
Source: https://docs.searchable.com/getting-started/plans-pricing
Review Searchable plan and billing sources
## Plans
Searchable plans scale by the number of domains, pages, prompts, and team workflows you manage. Exact limits depend on your plan and contract.
See the [pricing page](https://searchable.com/pricing) for current plans, or your workspace billing page for the limits that apply to your account.
## Custom Plans
Custom plans are available for larger domain portfolios, higher audit volume, and tailored onboarding. Contact your account team when your workspace needs limits beyond the plan shown in billing.
# Understanding Your Dashboard
Source: https://docs.searchable.com/getting-started/understanding-dashboard
Navigate your Searchable dashboard and complete the essential setup steps
**On this page:** Dashboard Overview • Essential Getting Started Steps • Dashboard Navigation • Understanding Your Scores • Daily Workflow • Common Questions
## Dashboard Overview
Your project dashboard is mission control for monitoring and improving your AI visibility. Once you create your project, you'll see a progress-based checklist that guides you through 5 essential setup steps.
**What you'll accomplish:**
* Train your AI agent with your brand context
* Understand your current AI visibility baseline
* Optimize prompts for better tracking
* Identify and fix technical issues
* Create your first AI-optimized content
The checklist tracks your progress automatically. Complete these 5 steps to unlock the full power of Searchable.
## Essential Getting Started Steps
Complete these actions in order to set up your workspace for success. Each step builds on the previous one.
### Step 1: Update Your Knowledge Base
**Time required:** 10-15 minutes\
**Navigate to:** Dashboard → Knowledge Base
**What it is:**\
Your knowledge base is where you teach Searchable's AI agent about your brand, products, and business context. This enables personalized recommendations throughout the platform.
**What to include:**
* **Brand Overview**: Company description, mission, and key differentiators
* **Products/Services**: What you offer and who it's for
* **Target Audience**: Who your ideal customers are
* **Competitors**: Main competitors you want to track
* **Business Goals**: What you want to achieve with AI visibility
**Why it matters:**\
A well-trained agent provides better content suggestions, more accurate competitive analysis, and personalized optimization recommendations.
**How to complete:**
Click "Knowledge Base" in the sidebar or use the checklist link
Upload documents, paste website copy, or write directly in the editor
Add 3-5 main competitors for comparative analysis
Specify what success looks like (traffic, visibility, rankings)
Save your knowledge base and ask the agent a question to verify it understands your brand
✓ Knowledge base updated - Move to Step 2
***
### Step 2: Review Your Visibility Report
**Time required:** 5 minutes\
**Navigate to:** Dashboard → Analytics → Visibility
**What it shows:**\
Your visibility report tracks how often and where your brand is mentioned across 4 major AI platforms: ChatGPT, Gemini, Perplexity, and Claude.
**Key metrics to understand:**
0-100 score showing how prominently you appear in AI responses
Percentage of prompts that mention your brand
Your mentions vs. competitors in your category
Which AI engines cite you most frequently
**What to look for:**
* **Current baseline**: This is your starting point - don't worry if it's low initially
* **Platform differences**: Some AI engines may know you better than others
* **Zero mentions**: Completely normal for new brands - you'll improve this with content
* **Competitor comparison**: See who's dominating AI visibility in your space
**Action items from the report:**
* Note which prompts get mentions (double down on these topics)
* Identify zero-mention prompts (content opportunities)
* Check which competitors are cited (learn from their content)
* Set realistic improvement targets (5-10% monthly is excellent)
Learn more about visibility metrics in [AI Visibility Tracking](/using-searchable/visibility-tracking).
✓ Visibility report reviewed - Move to Step 3
***
### Step 3: Review Prompts Analytics
**Time required:** 10 minutes\
**Navigate to:** Dashboard → Prompts
**What it shows:**\
Your prompts page displays performance for every question you're tracking across AI platforms. This is where you optimize what you're monitoring.
**Initial setup:**\
Searchable generates 20 starter prompts when you create your project:
* 3 brand-specific prompts (direct mentions)
* 17 semantic prompts (category and problem-solution queries)
**What to analyze:**
**Prompts with mentions (green indicators)**
These are working! Actions:
* Note the pattern - what makes them successful?
* Create similar prompts on related topics
* Track trends over time
**Prompts with no citations (red indicators)**
These are opportunities! Actions:
* Create comprehensive content targeting these prompts
* Ensure content directly answers the question
* Add structured data and clear formatting
* Check back in 2-4 weeks after publishing
**Different results across AI engines**
This reveals platform preferences:
* ChatGPT favors authoritative sources
* Claude values comprehensive explanations
* Perplexity prioritizes recent content
* Gemini integrates with Google's knowledge graph
**How to optimize:**
Sort prompts by mention rate to see what's working
Click "+ New Prompt" to add questions your customers actually ask
Refine prompt wording to be more specific and natural
Remove prompts that don't align with your goals (saves quota)
Use zero-mention prompts as your content roadmap
**Prompt limits by plan:**
* Starter: 50 unique tracked prompts
* Professional: 100 unique tracked prompts
* Agency: 1,000 unique tracked prompts
* Custom: Configured with your account team
Quality over quantity! 20-50 well-chosen prompts often outperform hundreds of generic ones.
✓ Prompts optimized - Move to Step 4
***
### Step 4: Audit Your Site Content
**Time required:** 5 minutes to review, varies to fix\
**Navigate to:** Dashboard → On-Page → Site Health
**What it does:**\
The site audit analyzes your website for technical SEO, content quality, and AEO (Answer Engine Optimization) issues. You'll receive a comprehensive report with prioritized recommendations.
**What you'll see:**
Page speed, mobile-friendliness, Core Web Vitals
Content quality, keyword optimization, structure
AI-readiness, structured data, citation-worthiness
Combined weighted score (0-100)
**Priority fixes to start with:**
1. **Critical Issues (Red)**
* Fix immediately - these severely impact all scores
* Usually: broken links, missing meta tags, severe performance issues
* Expected impact: 10-20 point score increase
2. **High Priority (Orange)**
* Address within first week
* Usually: page speed, mobile usability, missing structured data
* Expected impact: 5-15 point score increase
3. **Quick Wins**
* Look for the "Quick Wins" section
* High-impact, low-effort improvements
* Usually: alt text, internal linking, meta descriptions
* Expected impact: 3-8 point score increase per fix
**How to use the audit:**
Check your Technical, Content, and AEO scores - this is your baseline
Start with critical issues, then high-priority ones
Follow recommendations for each issue (code examples provided)
Run a new audit after fixes to measure improvement
Don't try to fix everything at once. Focus on critical issues first, then tackle 2-3 high-priority items each week.
Learn more in [Site Audits Guide](/using-searchable/site-audits) and [Understanding Scores](/using-searchable/understanding-scores).
✓ Audit reviewed and fixes prioritized - Move to Step 5
***
### Step 5: Create Your First Article
**Time required:** 20-30 minutes\
**Navigate to:** Dashboard → Create → Articles
**Why content comes last:**\
You've now trained your agent, understand your visibility baseline, optimized your prompts, and identified technical issues. You're ready to create content that will actually get cited by AI platforms.
**What the content generator does:**
* **Researches** your topic across the web
* **Analyzes** top-ranking content and competitor approaches
* **Generates** SEO and AEO-optimized articles
* **Includes** proper citations and structured data
* **Optimizes** for both Google and AI platforms
**How to create your first article:**
Start with a zero-mention prompt from Step 3 - this is your biggest opportunity
* How-to guide (most effective for AI citations)
* Product comparison
* Ultimate guide
* FAQ page
* Target keyword (from your prompt)
* Desired word count (2,000-3,000 words recommended)
* Tone and style preferences
Review the AI-generated outline and adjust if needed
Let AI create the complete article with citations
Add your unique insights, examples, and brand voice
Publish directly to your CMS or copy the content
**Publishing options:**
* Copy/paste to your CMS
* Download as Markdown or HTML
* Save as draft for later
**After publishing:**
* Track article performance in Analytics tab
* Monitor for AI citations (usually 2-4 weeks to appear)
* Update and refresh quarterly for best results
Your first article targets a zero-mention prompt. After publishing, create content for 2-3 more zero-mention prompts each month. This is how you build AI visibility systematically.
✓ First article created - Checklist complete!
***
## Dashboard Navigation Quick Reference
Now that you understand the essential workflow, here's how to navigate the dashboard.
### Top Navigation
Switch between workspaces and projects (top-left)
Run Audit, Add Page, AI Assistant (top-right)
Settings, Billing, Help, Logout
### Main Tabs
The sidebar contains your primary navigation:
* **Overview**: Dashboard home with scores and activity
* **Pages**: All monitored pages with individual scores
* **Issues**: Technical and content problems to fix
* **Prompts**: AI visibility tracking and prompt management
* **Content**: Article generation and content calendar
* **Analytics**: Deep dive into visibility data and trends
* **Settings**: Project configuration and integrations
### Sidebar Menu
**Project-Specific:**
* Dashboard, Pages, Issues, Prompts, Content, Analytics, Settings
**Global:**
* All Projects, Account, Billing, Team, API Keys, Help
## Understanding Your Scores
Four key metrics appear on every dashboard view:
### Overall Health Score (0-100)
Your combined optimization score calculated as:
```
Overall Health = (Technical × 30%) + (Content × 35%) + (AEO × 35%)
```
**Interpretation:**
* **90-100**: Excellent - Well-optimized site
* **70-89**: Good - Minor improvements recommended
* **50-69**: Fair - Several issues need attention
* **Below 50**: Poor - Significant work needed
### Technical Score (0-100)
Measures site performance and technical SEO:
* Page speed and Core Web Vitals
* Mobile-friendliness
* Crawlability and indexing
* Technical SEO fundamentals
### Content Score (0-100)
Evaluates content quality and optimization:
* Content depth and value
* Keyword optimization
* Structure and readability
* Internal linking
* Meta data completeness
### AEO Score (0-100)
Answer Engine Optimization readiness:
* Structured data implementation
* Citation-worthy content
* Clear answer formatting
* Topic authority
* AI model accessibility
For detailed explanations of each score and how to improve them, see [Understanding Scores](/using-searchable/understanding-scores).
## After Checklist Completion
Once you've finished the 5 essential steps, establish a daily workflow:
### Morning Routine (5 minutes)
Review overnight changes in scores and AI mentions
Identify high-impact, low-effort improvements
Check for critical issues or significant visibility changes
### Daily Tasks (10-15 minutes)
Review new issues in Issues tab - fix critical items immediately
Monitor prompt performance - note any significant changes
Check AI visibility trends - celebrate improvements
### Weekly Review (30 minutes)
* Which prompts gained mentions?
* Which need better content?
* Add 3-5 new prompts based on insights
* Choose 2-3 zero-mention prompts
* Schedule article creation
* Update existing content if needed
* Tackle 2-3 high-priority issues from audit
* Re-audit affected pages
* Track score improvements
### Monthly Strategy (1-2 hours)
* **Review overall trends**: Compare month-over-month improvements
* **Competitive analysis**: How are competitors performing?
* **Content performance**: Which articles drive the most AI citations?
* **Goal assessment**: Are you hitting your visibility targets?
* **Strategy adjustment**: What's working? What needs to change?
## Dashboard Features by Tab
### Overview Tab
Your default landing page showing:
* Health scores with trend indicators
* Recent activity feed
* Quick wins section
* Performance charts
### Pages Tab
Monitor all your website pages:
* Individual page scores
* Issues per page
* Last audited timestamp
* Bulk actions available
### Issues Tab
All detected problems across your site:
* Grouped by severity (Critical → Low)
* Filterable by type (Technical, Content, AEO)
* Actionable fix recommendations
* Track resolution progress
### Prompts Tab
Manage AI visibility tracking:
* All tracked prompts with performance metrics
* Add/edit/archive prompts
* Bulk import from CSV
* Performance analytics per prompt
### Content Tab
AI-powered content workspace:
* Draft and published articles
* Content generation tools
* Performance tracking
* Publishing integrations
### Analytics Tab
Deep dive into data:
* Visibility trends over time
* Competitor comparisons
* Citation analysis
* Traffic correlation (with GA4)
## Common Questions
Excellent! Now you transition to the daily/weekly workflow above. Focus on:
1. Creating content for zero-mention prompts (2-3 articles/month)
2. Fixing high-priority issues from audits
3. Monitoring visibility trends and competitor movements
4. Refining your prompt strategy based on performance
The checklist gets you started; the ongoing workflow builds long-term AI visibility.
Technically yes, but not recommended. Each step builds on the previous:
* Without knowledge base: Generic recommendations, no personalization
* Without visibility baseline: No benchmark to measure progress
* Without prompt optimization: Wasted tracking quota on poor prompts
* Without audit: Missing critical issues that hurt AI visibility
* Without first article: No content for AI models to cite
Complete all 5 steps for best results. Takes about 1 hour total.
**Daily (5-10 min):**
* Check Overview for critical issues or major changes
* Review notifications
* Monitor visibility score trends
**Weekly (30 min):**
* Analyze prompt performance
* Plan content based on gaps
* Fix 2-3 high-priority issues
**Monthly (1-2 hours):**
* Strategic review of all metrics
* Competitive analysis
* Adjust goals and strategy
Don't obsess over daily fluctuations - focus on weekly/monthly trends.
Follow the checklist order:
1. **Create/Agent**: Set up knowledge base (once)
2. **Analytics**: Understand visibility baseline (review, then weekly)
3. **Prompts**: Optimize tracking (review, then weekly)
4. **Optimize**: Fix issues (ongoing, prioritized by severity)
5. **Content**: Generate articles (2-3 per month)
After initial setup, spend most time on **Issues** (fixing problems) and **Content** (creating articles).
**Real-time:**
* Issue status changes
* Team activity
* Content drafts
**Hourly:**
* AI visibility data
* Prompt mention checks
**Continuous (within plan limits):**
* Page audits run on your schedule
* Starter: 25 pages/month
* Professional: 100 pages/month
* Agency: 500 pages/month
* Custom: Tailored allocation
**Historical Data:**
* Starter: 3 months retention
* Professional: 12 months retention
* Agency & Custom: Unlimited retention
Yes! Invite team members in **Settings** → **Team**.
**Team member limits:**
* Starter: 1 seat (just you)
* Professional: 10 seats
* Agency: 25 seats
* Custom: Contracted allocation
**Roles available:**
* Admin: Full access including billing
* Editor: Edit content and settings
* Viewer: Read-only access
All team members see the same checklist progress and can collaborate on completing steps.
Some metrics require integrations or sufficient data:
**Missing traffic data:** Connect Google Analytics 4 in Settings → Integrations
**Missing keyword data:** Connect Google Search Console in Settings → Integrations
**Incomplete scores:** New sites need at least one full audit cycle (wait 24-48 hours)
**Zero AI mentions:** Normal for new brands - build content and give AI models 2-4 weeks to update
## Dashboard Performance
If your dashboard loads slowly:
1. **Reduce Date Range**: View last 30 days instead of 12 months
2. **Limit Pages**: Focus monitoring on priority pages only
3. **Clear Filters**: Reset any active filters on tables
4. **Check Connection**: Ensure stable internet connection
5. **Contact Support**: Email [support@searchable.com](mailto:support@searchable.com) if issues persist
## Next Steps
Deep dive into what each score means and how to improve them
Master advanced prompt strategies and templates
Comprehensive guide to running and interpreting audits
Advanced content creation and optimization techniques
Connect Google Search Console, GA4, and your CMS
Upgrade for higher limits and advanced features
# Google Analytics 4 Integration
Source: https://docs.searchable.com/integrations/google-analytics-4
Connect GA4 to track traffic, conversions, and user behavior from AI platforms
## Overview
Integrate Google Analytics 4 with Searchable to understand how AI visibility translates to website traffic and conversions. Track user journeys from AI platforms to your site.
GA4 integration is available on Professional, Agency, and Custom plans.
## Benefits
See which AI platforms drive visitors
Measure ROI of AI visibility efforts
Understand how AI-referred users interact
Calculate financial value of AI mentions
### What Data Gets Synced
* **Traffic Sources**: Where visitors come from (including AI platforms)
* **User Behavior**: Pages viewed, time on site, bounce rate
* **Conversions**: Goal completions and e-commerce transactions
* **Demographics**: Age, gender, interests (aggregated)
* **Technology**: Device, browser, OS
* **Events**: Custom events and interactions
* **Engagement**: Session duration, scroll depth, clicks
## Prerequisites
Have Google Analytics 4 property set up for your website
Editor or Administrator access to the GA4 property
At least 7 days of traffic data in GA4
Searchable Professional, Agency, or Custom plan
Viewer access in GA4 is insufficient. You need Editor or Administrator permissions to connect.
## Setup Guide
In Searchable:
1. Go to **Settings** → **Integrations**
2. Find **Google Analytics 4**
3. Click **Connect**
1. Select your Google account
2. Review permissions
3. Click **Allow**
**Permissions needed:**
* View Analytics data
* Edit Analytics configuration (for enhanced tracking)
Choose your property:
* Select the correct GA4 property (not Universal Analytics)
* Multiple properties? Choose your main website
* Can connect additional properties later
Enable advanced features:
**AI Referrer Tracking:**
* Automatically tags traffic from AI platforms
* Creates custom dimensions for AI sources
* Tracks specific AI models (ChatGPT, Claude, etc.)
**Event Tracking:**
* Tracks AI-related events
* Content engagement from AI visitors
* Conversion attribution
Recommended: Enable enhanced tracking for complete insights.
* Click **"Start Sync"**
* First sync takes 1-3 minutes
* Historical data import (last 30 days)
* Email notification when complete
Check that data is flowing:
1. Go to **Analytics** tab
2. See GA4 widgets and charts
3. Verify traffic numbers match GA4
4. Check "Last Synced" timestamp
## AI Traffic Attribution
### How Searchable Tracks AI Referrers
When enhanced tracking is enabled:
**UTM Parameters:**
```text theme={null}
?utm_source=chatgpt&utm_medium=ai&utm_campaign=searchable_tracking
```
**Custom Dimensions:**
* `ai_platform`: Which AI model (ChatGPT, Claude, Gemini, etc.)
* `ai_prompt`: Which tracked prompt drove the visit (hashed)
* `ai_session`: Session identifier from AI platform
**Referrer Detection:**
* Direct traffic analysis
* URL pattern matching
* Custom JavaScript tracking
* Server-side attribution
### Viewing AI Traffic
In Searchable Analytics:
**Metrics Available:**
* Sessions from each AI platform
* Page views per AI source
* Average session duration
* Bounce rate by AI platform
* Conversions attributed to AI
* Revenue from AI-referred traffic
## Conversion Tracking
### Setting Up Goals
Define what counts as a conversion:
**E-commerce:**
* Purchases
* Add to cart
* Checkout initiated
* Revenue tracking
**Lead Generation:**
* Form submissions
* Email signups
* Demo requests
* Contact form fills
**Engagement:**
* Time on site > X minutes
* Pages per session > X
* Scroll depth > X%
* Video plays
### AI Conversion Attribution
See which prompts drive conversions:
1. **Direct Attribution**: User converts in same session
2. **Assisted Conversions**: AI visit assists later conversion
3. **Multi-Touch**: AI touchpoint in longer journey
**Example Report:**
```text theme={null}
Prompt: "What are the best CRM tools for startups?"
- Sessions: 145
- Conversions: 12
- Conversion Rate: 8.3%
- Revenue: $4,800
- ROI: $33 per mention
```
## User Behavior Analysis
### AI Visitor Behavior
Compare AI-referred vs. other visitors:
| Metric | AI-Referred | Organic Search | Direct |
| -------------------- | ----------- | -------------- | ------ |
| Avg Session Duration | 4:32 | 2:15 | 3:05 |
| Pages / Session | 4.2 | 2.3 | 3.1 |
| Bounce Rate | 32% | 58% | 45% |
| Conversion Rate | 5.2% | 2.8% | 3.9% |
**Insights:**
* AI-referred visitors often spend more time
* Higher engagement and conversion rates
* Different page paths and interests
### Content Performance
See which content attracts AI-referred visitors:
* Most viewed pages
* Entry pages from AI
* Exit pages
* Content engagement
* Internal navigation patterns
## Dashboard Widgets
### Traffic Overview
* Total visitors
* AI vs. non-AI breakdown
* Traffic trends over time
* Platform distribution
### Conversion Funnel
* Visitors → Engaged → Converted
* Drop-off points
* Conversion rates by source
* Revenue attribution
### Real-Time
* Active users now
* Traffic sources (live)
* Popular pages
* Recent conversions
### Audience Insights
* Demographics
* Interests
* Technology
* Geographic distribution
## Data Refresh
| Plan | Sync Frequency | Historical Data | Delay |
| ------------ | -------------- | --------------- | ----------- |
| Professional | Hourly | 90 days | 24 hours\* |
| Agency | Real-time | Unlimited | Real-time\* |
| Custom | Real-time | Custom | SLA-based |
\*Google Analytics 4 has inherent data processing delays of 24-48 hours
## Troubleshooting
**Common Issues:**
* Insufficient GA4 permissions
* Wrong property type (UA vs. GA4)
* Account access issues
**Solutions:**
* Verify Editor/Admin access in GA4
* Ensure using GA4 (not Universal Analytics)
* Try different Google account
* Check GA4 property is active
**Possible Causes:**
* Brand new property (no data yet)
* Wrong property selected
* GA4 not receiving traffic
* Filters excluding data
**Check:**
* Property has data in GA4 directly
* Selected correct property
* GA4 tracking code is installed
* Wait 24-48 hours for data processing
**Why This Happens:**
* Enhanced tracking not enabled
* AI visitors use VPNs/privacy tools
* Insufficient sample size
* Attribution window too short
**Solutions:**
* Enable enhanced tracking in integration settings
* Wait for more data (needs 100+ visitors)
* Adjust attribution window
* Verify tracking parameters are working
## Privacy & Compliance
**Data Handling:**
* Only aggregated data is stored
* No personally identifiable information
* GDPR and CCPA compliant
* User privacy respected
**Cookie Consent:**
* Searchable respects your existing consent setup
* No additional cookies required
* Works with consent management platforms
**Data Retention:**
* Pro: 90 days
* Agency: Unlimited retention
* Custom: Custom retention windows
* Can be deleted anytime
## Advanced Features (Custom)
### Custom Reports
Build custom dashboards:
* Drag-and-drop metrics
* Custom dimensions
* Calculated fields
* Scheduled exports
### Predictive Analytics
AI-powered predictions:
* Conversion probability
* Churn likelihood
* Lifetime value
* Trend forecasting
### Cross-Domain Tracking
Track users across multiple properties:
* Main site + subdomain
* Multiple brand websites
* App + web tracking
### Data Studio Integration
Export to Google Data Studio:
* Pre-built templates
* Custom visualizations
* Automated reporting
* Stakeholder dashboards
## Best Practices
Enable enhanced tracking for AI attribution
Set up conversion goals from day one
Monitor AI traffic weekly
Compare AI vs. organic visitor behavior
Use insights to optimize prompt strategy
Track ROI of AI visibility efforts
## Use Cases
### Calculate AI ROI
```text theme={null}
Monthly AI Mentions: 500
AI-Referred Sessions: 250
Conversions: 20
Conversion Value: $100
Total Revenue: $2,000
Cost of Searchable Pro: $49
ROI: 4,000% ($2,000 / $49)
```
### Optimize Content
1. Identify pages with high AI traffic
2. See which ones convert best
3. Create similar content
4. Optimize low-converting pages
### Improve Prompts
1. Track which prompts drive most traffic
2. Measure conversion rates per prompt
3. Double down on high-converters
4. Refine or remove low-performers
## Disconnecting GA4
To disconnect:
1. Settings → Integrations
2. Click "Disconnect" on GA4
3. Confirm disconnection
**What Happens:**
* No new data synced
* Historical data preserved (30 days)
* Can reconnect anytime
* No impact on your GA4 property
## Next Steps
Add GSC for complete SEO data
Turn insights into better content
Master the analytics dashboard
Measure AI-driven performance
# Google Search Console Integration
Source: https://docs.searchable.com/integrations/google-search-console
Connect Google Search Console to enrich your SEO and AEO data
## Overview
Connecting Google Search Console (GSC) to Searchable unlocks powerful insights by combining traditional SEO data with AI visibility metrics. See which keywords drive both Google rankings and AI mentions.
GSC integration is available on Professional, Agency, and Custom plans.
## Benefits
See which keywords perform in both Google and AI platforms
Understand how SEO and AEO work together
Identify crawl errors and indexing problems
Monitor impressions, clicks, CTR, and position
### What Data Gets Synced
* **Keywords**: Queries, impressions, clicks, CTR, average position
* **Pages**: Top performing pages and their metrics
* **Countries**: Geographic performance data
* **Devices**: Desktop, mobile, tablet breakdown
* **Search Appearance**: Rich results, AMP, etc.
* **Coverage**: Indexing status and errors
* **Core Web Vitals**: Performance metrics
* **Mobile Usability**: Mobile-specific issues
## Prerequisites
Before connecting GSC to Searchable:
Have a verified Google Search Console property for your domain
Owner or Full User permission in GSC (not just Restricted access)
At least 28 days of data in GSC (for meaningful analysis)
Searchable Professional, Agency, or Custom plan
Restricted Users in GSC cannot connect integrations. You need Owner or Full User access.
## Setup Guide
In your Searchable project:
1. Go to **Settings**
2. Click **Integrations**
3. Find **Google Search Console**
4. Click **Connect**
A popup window opens:
1. Select your Google account
2. Review permissions requested
3. Click **Allow**
**Permissions needed:**
* View Search Console data
* View and manage your properties
Searchable only reads data - we never modify your GSC settings or data.
Choose the GSC property to connect:
**Property Types:**
* **Domain property**: Recommended (covers all subdomains and protocols)
* **URL prefix**: Only covers specific protocol and subdomain
If you have both types, choose the Domain property for complete coverage.
Set your preferences:
**Sync Frequency:**
* Hourly (recommended for most users)
* Daily (for large sites to reduce API usage)
* Manual (sync on-demand only)
**Data Range:**
* Last 7 days
* Last 28 days (recommended)
* Last 90 days (maximum)
**Filters:**
* Include/exclude specific queries
* Country filters
* Device type filters
Click **"Start Initial Sync"**
* First sync takes 2-5 minutes
* You'll receive an email when complete
* Data appears in Analytics tab
Initial sync imports the full date range. Subsequent syncs only import new data.
Confirm everything is working:
1. Go to **Analytics** tab
2. Look for GSC data widgets
3. Check "Last Synced" timestamp
4. Verify data looks accurate
## Using GSC Data in Searchable
### Keyword Analysis
**Combined View:**
* See which keywords rank in Google AND get AI mentions
* Identify high-potential keywords with good SEO but no AI presence
* Find keywords where AI visibility exceeds Google rankings
**Optimization Opportunities:**
* Keywords with high impressions but low AI visibility
* Keywords ranking well in AI but not in Google
* High-CTR keywords to target with content
### Page Performance
**Metrics per Page:**
* Google impressions and clicks
* AI mention frequency
* Combined visibility score
* Traffic sources breakdown
**Insights:**
* Which pages drive most organic traffic
* Which pages get AI citations
* Content gaps and opportunities
* Pages needing optimization
### Search Analytics
**Filters and Segmentation:**
* By date range
* By device (mobile, desktop, tablet)
* By country
* By search appearance
* By query type
**Exports:**
* CSV download of all data
* Custom reports
* Scheduled email reports
## Data Refresh Schedule
| Plan | Sync Frequency | Historical Data | Real-time Updates |
| ------------ | -------------- | --------------- | ----------------- |
| Professional | Hourly | 90 days | Yes |
| Agency | Real-time | Unlimited | Yes |
| Custom | Real-time | Custom | Yes + API |
Google Search Console data has a 2-3 day delay from Google. This is a GSC limitation, not Searchable.
## Understanding the Combined Dashboard
### SEO + AEO Correlation
**High SEO, High AEO** (Top Right Quadrant)
* Your best performing content
* Maintain and expand on these topics
* Use as templates for new content
**High SEO, Low AEO** (Top Left Quadrant)
* Good traditional SEO but AI models don't cite you
* Opportunity: Optimize for AI visibility
* Add structured data, improve answer formats
**Low SEO, High AEO** (Bottom Right Quadrant)
* AI models cite you but Google rank is low
* Opportunity: Improve traditional SEO
* Build backlinks, optimize technical SEO
**Low SEO, Low AEO** (Bottom Left Quadrant)
* Content needs comprehensive optimization
* Consider rewriting or consolidating
* May not be worth the effort vs. creating new content
### Traffic Attribution
See how traffic sources contribute:
```text Example: Traffic Breakdown theme={null}
Total Organic Traffic: 10,000 visitors/month
From Google Search: 8,500 (85%)
From AI Platforms: 1,200 (12%)
From Other Search: 300 (3%)
AI-Referred Conversion Rate: 4.2%
Google-Referred Conversion Rate: 2.8%
```
## Troubleshooting
**Common Causes:**
* Insufficient GSC permissions
* Account not verified in GSC
* Using personal vs. organizational account
**Solutions:**
* Verify you have Owner or Full User access
* Check property is verified in GSC
* Try using a different Google account
* Clear browser cookies and retry
**Possible Reasons:**
* Recently created property (needs 28 days of data)
* Wrong property selected
* Filters excluding all data
* Sync hasn't completed yet
**Check:**
* Property has data in GSC directly
* Selected correct property in Searchable
* Sync status shows "Connected"
* Last sync timestamp is recent
**Error Messages:**
* "Rate limit exceeded": Wait 1 hour, then retry
* "Property not found": Re-verify property ownership in GSC
* "Authentication expired": Disconnect and reconnect
* "Insufficient permissions": Check GSC access level
**Solution:**
Most sync errors resolve by:
1. Disconnecting integration
2. Clearing browser cache
3. Reconnecting with fresh authentication
**Why Data May Differ:**
* Time zone differences
* Date range selection
* Filters applied in Searchable
* GSC data still processing
* Different aggregation methods
**What to Do:**
* Verify same date range in both platforms
* Check timezone settings match
* Remove any active filters
* Allow 24 hours for data to fully sync
## Privacy & Data Handling
**What Searchable Stores:**
* Keyword and page performance metrics
* Aggregated statistics only
* No personally identifiable information
* No individual search query data
**Data Retention:**
* Pro: 90 days of historical data
* Agency: Unlimited retention
* Custom: Custom retention windows
**Data Deletion:**
* Disconnect integration to stop new data sync
* Historical data deleted after 30 days
* Immediate deletion available on request
## Advanced Features
### Custom Dimensions (Custom)
Create custom segments:
* By branded vs. non-branded keywords
* By commercial intent
* By content type
* By funnel stage
### Automated Alerts
Get notified when:
* Ranking drops significantly
* New high-volume keywords discovered
* CTR falls below threshold
* Impressions surge or drop
### API Access
Query GSC data via Searchable API:
```javascript Example: Fetch GSC Keywords theme={null}
const response = await fetch(
'https://api.searchable.com/v1/gsc/keywords',
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
projectId: 'your-project-id',
dateRange: 'last28days',
limit: 100
})
}
);
const data = await response.json();
```
## Best Practices
Sync at least 28 days of data for reliable trends
Review GSC insights weekly alongside AI visibility data
Use keyword gaps to inform content strategy
Monitor both SEO and AEO for complete picture
Set up alerts for significant ranking changes
Export data monthly for stakeholder reports
## GSC + Searchable Use Cases
### Content Gap Analysis
1. Identify keywords with high impressions, low clicks
2. Check if AI models cite you for those keywords
3. If yes: Optimize for Google (improve title, meta, CTR)
4. If no: Create better content that answers the query
### Competitive Research
1. Find keywords where you rank on page 2-3
2. Check if competitors get AI citations
3. Create superior content optimized for both
4. Track progress in unified dashboard
### ROI Measurement
1. Track organic traffic from GSC
2. Measure AI-referred traffic
3. Calculate conversion rates for each
4. Determine which channel drives more value
## Disconnecting GSC
To disconnect Google Search Console:
1. Go to Settings → Integrations
2. Find Google Search Console
3. Click **"Disconnect"**
4. Confirm disconnect
**What Happens:**
* No new data is synced
* Historical data preserved for 30 days
* Can reconnect anytime
* No impact on your actual GSC account
## Next Steps
Add GA4 for complete traffic insights
Optimize your keyword approach
Master the analytics dashboard
Access data programmatically
# MCP Integration
Source: https://docs.searchable.com/integrations/mcp
Connect Searchable to Claude, ChatGPT, Grok, Gemini, Microsoft Copilot agents, and other MCP-compatible assistants.
## What is MCP?
The **Model Context Protocol (MCP)** is an open standard that lets AI assistants connect to external tools and data sources. Searchable's MCP server lets you ask AI assistants questions about your AI visibility, site audits, and content — without leaving the assistant.
Compatible clients include:
* **Claude.ai** (web and mobile) — add as a connector
* **ChatGPT** — via developer-mode connectors
* **Grok** — via custom MCP connectors
* **Gemini Spark** — via custom Connected Apps
* **Microsoft 365 Copilot agents** and **Microsoft Copilot Studio**
* **Claude Desktop** and **Claude Code**
* **Cursor**
* **Windsurf**, **Perplexity Enterprise**, **Mistral**, and other MCP-compatible clients
The assistant controls whether custom MCP servers are available for your account, plan, and region.
Gemini custom apps currently require Gemini Spark eligibility, a US personal Google Account, and
English.
For Microsoft, this compatibility applies to Microsoft 365 Copilot agents and Copilot Studio — not
the consumer Microsoft Copilot chat product, which does not currently document a bring-your-own MCP
server flow.
Ask questions like *"What's my brand's visibility score on ChatGPT?"* or *"What critical AEO
issues does my site have?"* and the assistant will query Searchable for live data.
**Plan requirement:** MCP integration requires a paid Searchable plan. Both connection methods —
signing in with OAuth and API keys — are unavailable on the Free plan.
## How authentication works
The Searchable MCP server uses **OAuth 2.1 with PKCE**. It supports the current MCP client-metadata
discovery flow, plus Dynamic Client Registration for clients that still require it. Public clients
use PKCE; compatible enterprise clients can use a dynamically issued client secret. This means a
new standards-compatible assistant can connect without Searchable adding a provider-specific OAuth
integration first.
You do **not** paste an API key into your MCP client's config — you sign in and approve access, just
like connecting any other app:
1. You add the server URL to your client (`https://app.searchable.com/api/mcp-server/mcp`).
2. On first use, the client opens Searchable in your browser and asks you to **log in** (or reuses your existing session).
3. A **consent screen** shows which application is connecting and lets you choose:
* **Which projects** it can access — pick specific ones, or leave all selected (all also covers projects you create later).
* **Read-only** (default) or **Read & write** access.
4. You click **Authorize**. Your client receives an OAuth access token scoped to exactly what you approved and uses it for subsequent requests.
The token can never exceed what you granted on the consent screen — a read-only, single-project grant stays read-only and single-project.
Only connect the Searchable MCP from trusted clients. Grant the narrowest access you need —
read-only, and only the projects the assistant should see.
## Setup
**Server URL:** `https://app.searchable.com/api/mcp-server/mcp` — the same address for every
client below.
### Step 1: Add the server to your client
1. Open Claude.ai → **Settings → Connectors**.
2. Click **Add custom connector**.
3. Enter URL: `https://app.searchable.com/api/mcp-server/mcp`
4. Claude opens the Searchable sign-in and consent page — continue with Step 2.
ChatGPT connects through developer-mode connectors (available on ChatGPT Plus and Pro):
1. Open ChatGPT → **Settings → Apps & Connectors → Advanced settings** and enable **Developer mode**.
2. Back in **Apps & Connectors**, click **Create** to add a connector.
3. Enter URL: `https://app.searchable.com/api/mcp-server/mcp` and choose **OAuth** authentication.
4. ChatGPT opens the Searchable sign-in and consent page — continue with Step 2.
In a chat, enable the Searchable connector from the composer's tools menu, then ask away.
Add the server from your terminal:
```bash theme={null}
claude mcp add searchable --transport http https://app.searchable.com/api/mcp-server/mcp
```
Then inside a session run `/mcp`, pick **searchable → Authenticate** — your browser opens the Searchable sign-in and consent page. Continue with Step 2.
Add to `~/.claude/mcp.json`:
```json theme={null}
{
"mcpServers": {
"searchable": {
"url": "https://app.searchable.com/api/mcp-server/mcp"
}
}
}
```
Restart Claude Desktop. On first use it opens the Searchable sign-in and consent page in your browser — continue with Step 2.
Click to install with one step — Cursor opens, shows the server, and you confirm:
Or add manually to `.cursor/mcp.json`:
```json theme={null}
{
"mcpServers": {
"searchable": {
"url": "https://app.searchable.com/api/mcp-server/mcp"
}
}
}
```
Either way, Cursor discovers OAuth automatically — no manual `auth` block needed. On first use it opens the Searchable sign-in and consent page in your browser — continue with Step 2.
Add to your Windsurf MCP configuration:
```json theme={null}
{
"mcpServers": {
"searchable": {
"url": "https://app.searchable.com/api/mcp-server/mcp"
}
}
}
```
For Grok, Gemini Spark, Microsoft 365 Copilot agents, Copilot Studio, Perplexity Enterprise,
Mistral, or another hosted assistant, create a custom MCP server or connector in that product and
use `https://app.searchable.com/api/mcp-server/mcp`. Searchable publishes OAuth discovery metadata, so choose OAuth
or automatic authentication when the host asks. The exact menu name and availability are controlled
by the host product.
### Step 2: Log in and authorize
The first time your client connects, Searchable opens in your browser:
1. **Log in** to Searchable (or continue with your existing session).
2. On the **consent screen**, choose which projects the client may access and whether it gets **Read-only** (default) or **Read & write** access.
3. Click **Authorize**. Your browser returns to the client, now connected — no API key to copy or paste.
Your login is the identity for this flow. To connect a script or a client that only accepts a
static bearer token, use the legacy API-key path below instead.
### Step 3: Verify the connection
Once connected, ask:
```
List my Searchable projects
```
You should see a list of your projects with their names and domains.
### Connect with an API key (legacy)
The OAuth login flow above is the recommended path for interactive MCP clients. For scripts, headless clients, or any client that only accepts a static bearer token, a Searchable **API key** works as a bearer token directly — the same `sea_` key the [REST API](/advanced/api-usage) accepts.
In **Settings → Workspace → Integrations**, click **Create API Key**, name it, and copy the key
(starts with `sea_`). Store it securely — you won't see it again. A key can be scoped to a
single project and to read or read-and-write, mirroring the consent options above.
Configure your client to send `Authorization: Bearer sea_...` on every request to
`https://app.searchable.com/api/mcp-server/mcp`. No login or consent screen is involved on this
path.
## Available tools
The Searchable MCP exposes **30 primary tools** — 27 read-only and 3 write (32 with the Associated Sources feature enabled), plus 4 deprecated names kept callable through their sunset window (see [Deprecated tool names](#deprecated-tool-names)). Every read tool is annotated `readOnlyHint: true`. Every tool that operates on a project takes a required `projectId` (get IDs from `list_projects`), and most read tools also accept an optional `response_format` — `"concise"` (default, summary + capped rows) or `"detailed"` (fuller rows, same shape).
Five tools exist purely to make assistants reliable, and are worth calling early in a session:
* **`get_current_date`** — the server's UTC date plus pre-computed window starts (7/30/90/365 days). Call it before interpreting relative time like "last month" so date math is never guessed.
* **`whoami`** — who this connection is authenticated as, its read/write scopes, and the project roster it can see. Call it when unsure what the connection can access.
* **`search_docs`** / **`read_doc`** — full-text search and retrieval over this documentation, so questions like "how is the visibility score calculated?" are answered in-chat, from the source.
* **`get_page_metrics`** — the per-URL rollup: one page's citations, AI-referral sessions, and AI-crawler hits as daily buckets, in one call.
The server also publishes two **resources** — `searchable://glossary` (compact index) and `searchable://glossary/full` (complete definitions) — metric and concept definitions with the tools that read each one, for hosts that attach resources as reference context.
`get_visibility`, `get_share_of_voice`, and `get_sentiment` additionally accept `compare: "previous_period" | "previous_year"` — the response gains a `comparison` block with the previous window's metrics and current-minus-previous deltas, so period-over-period questions are one tool call.
**Absolute date ranges.** The core analytics reads accept `from` and `to` (inclusive, UTC) as an
alternative to the relative `days` — `from: "2026-03-01", to: "2026-03-31"` answers "how did March
go" without arithmetic against today. Both bounds are required together, and they are **mutually
exclusive with `days`**: sending both is an `invalid_argument` error rather than a silent
precedence rule. Bare `YYYY-MM-DD` and full ISO timestamps are both accepted (the UTC day is what
counts). An over-long `days` is clamped to the tool's maximum, but an over-long explicit range is
**rejected** — narrowing a range you spelled out would answer a different question than the one
you asked. Supported on `get_visibility` (every `group_by`), `get_share_of_voice`,
`get_sentiment`, `get_topic_analysis`, and `get_ai_traffic` (every `report`), plus the matching
REST endpoints. Tools not in that list — `get_competitors`, `get_shopping_visibility`, `get_ads`,
`get_page_metrics`, `get_query_fanout`, `get_prompt_answers`, and the source reads — still take
`days` only. (`get_gsc_performance` has always had its own `startDate` / `endDate`.)
**Filter echo.** Every filterable read echoes an `appliedFilters` object: the platform / brand /
topic / location filters that call actually narrowed by, or `{}` when it was unfiltered. That
covers `get_visibility`, `get_share_of_voice`, `get_competitors`, `get_topic_analysis`,
`list_prompts`, `get_sentiment` (every view), `get_source_trends`, and `get_shopping_visibility`
(`summary` view). All of them except `get_topic_analysis` also return `availableFilters` (the
project's topics and countries) so a client can offer the next filter without a second round-trip
— on `get_visibility` that rides along on the `summary` and `platform` views. Use `appliedFilters`
to state what a number covers rather than presenting a filtered figure as the whole picture.
Write actions **are** MCP tools too: `generate_report`, `trigger_audit`, and `refresh_sitemap` are
available to keys/grants with the **write** scope, and each requires an explicit `confirm: true`
argument — without it the tool returns a dry-run preview and changes nothing. The REST equivalents
(e.g. `POST /api/mcp/projects/{projectId}/reports`) remain available; see [Advanced API
Usage](/advanced/api-usage).
### Projects
List all projects this connection can access — names, domains, and IDs. Call this FIRST: every other tool needs a `projectId`.
**Parameters:** `response_format` (optional)
### Visibility & share of voice
AI visibility for a project. `group_by` selects the view: `summary` (overall visibility score), `platform` (per ChatGPT/Claude/Gemini/Perplexity breakdown), `prompt` (per-prompt breakdown, paginated), `location` (per country/city), or `date` (the per-report time series — trend, uplift, before/after analysis; default 90-day window). The `unbranded`/`branded`, `topicId`, `country` and `locationId` filters work on every view except `date`, which accepts only `unbranded`/`branded`; the `platform` filter is restricted to `group_by=prompt|location`. An interactive Visibility Snapshot card also renders automatically beside the answer on Apps-capable clients — see below.
`group_by="topic"` was **removed**. Per-topic visibility now lives on its own tool, `get_topic_analysis` (next card), which returns the competitive rank, strengths, and gaps the old view never had. Passing `group_by="topic"` is now a validation error — switch the call to `get_topic_analysis`.
**`include`** attaches optional extra blocks (comma-separated): `industry_ranking` adds the competitive leaderboard — the **top 25** entities by visibility, with your own rank, share of voice, and change — to `group_by=summary|platform` (`hasMore` flags a longer field; `brandRankStatus` distinguishes ranking below the cutoff from being unranked, and `totalEntities` is null when truncated); `annotations` adds the dated markers (campaign launches, migrations) overlapping the window to `group_by=date`, so a spike comes back with its explanation attached. An `include` a view cannot attach is an `invalid_argument` error on **every** view — including `group_by=prompt` and `group_by=location`, which attach no blocks at all — never a response that quietly lacks the block.
**Parameters:** `projectId` (required), `group_by` (`"summary"` | `"platform"` | `"prompt"` | `"location"` | `"date"`, default summary), `days` (default 30, or 90 for `group_by=date`; max 365, or 180 for `group_by=prompt`), `unbranded`, `branded`, `platform`, `topicId`, `limit` (`group_by=prompt`, default 100, max 500), `offset` (`group_by=prompt`), `country`, `locationId` (all optional except `projectId`)
Per-topic AI visibility — the brand's mention rate in each topic, its competitive rank within that topic, how many tracked prompts sit under it, and the AI-identified attribute strengths and gaps behind the number. This is the **only** per-topic view: use it for any question about topics, subject areas, or categories, including where a brand is winning or losing and what to fix. Replaces the removed `get_visibility (group_by:"topic")`. An interactive Topic Analysis card also renders automatically beside the answer on Apps-capable clients — see below.
**`view="prompts"`** drills into ONE topic (`topicId` required): every prompt assigned to it with your average rank, its visibility, and which competitors outrank you — the "which specific questions are we losing" view behind a weak topic. A prompt you never appeared for reports `rank: null`, never `0`.
**`view="heatmap"`** returns average brand position per topic x AI platform — where you're strong on one engine and absent on another. There is deliberately no platform filter on this view: the platform axis is the answer.
**Parameters:** `projectId` (required), `view` (`topics` default, `prompts`, `heatmap` — `platform` is rejected on `heatmap`, whose axis IS platform), `topicId` (required for `view=prompts`; rejected on the default view, which lists every topic), `days` (default 30, max 365), `from`/`to`, `limit`, `platform`, `unbranded`, `branded` (all optional except `projectId`)
**Deprecated** — call `get_visibility` with `group_by: "date"` instead (same data, same parameters). This name keeps answering with an identical payload until its removal date; see [Deprecated tool names](#deprecated-tool-names).
**Parameters:** `projectId` (required), `days` (default 90, max 365), `unbranded`, `branded` (all optional except `projectId`)
Brand vs competitor share of voice — mention-share percentage and rank among all tracked entities, plus each entity's day-over-day (today vs yesterday) point change. `mentions`/`citations` aren't part of this view (mirrors the in-app Share of Voice sheet) — use `get_competitors` for those. An interactive Share of Voice card also renders automatically beside the answer on Apps-capable clients — see below.
**`group_by="date"`** returns the daily share series instead — your share and your top competitors', one point per day. That is the "is our share growing?" view; `include="annotations"` adds the dated markers explaining any jump. `compare` is not supported there (the series already shows the movement), and the interactive card hides itself on it.
**Parameters:** `projectId` (required), `group_by` (`summary` default, or `date`), `days` (default 30, max 365), `from`/`to`, `include`, `platform`, `topicId`, `unbranded`, `branded`, `country`, `locationId`, `compare` (all optional except `projectId`)
### Competitors
The project's real/tracked competitors, **ordered by rank (highest visibility first)** — visibility, share of voice, sentiment score, average mention position, and all-time mention count, plus a `brand` block carrying the same metrics for the project itself so the two sit on one ruler. Pass `competitorId` for a **head-to-head** against one competitor instead: `headToHead.brand` vs `headToHead.competitor`, each with visibility %, share of voice %, sentiment (0–100) and average position (a rank — **lower is better**), plus the phrases each is known for; for the competitor it also returns its rank, per-day history, and up to 10 recent prompts it was mentioned in. `competitorId` accepts either the competitor's ID or its **name exactly as the list shows it** (`competitorId: "Nike"`), so you can drill in straight from the list — `response_format: "detailed"` adds an `id` column if you want the exact key. A `null` metric means unmeasured in that window, not zero. `visibility`/`sov`/`sentimentScore`/`avgPosition` honor the filters; the list view's `mentions` is all-time and ignores them. On the head-to-head, `citations` (inline citations on responses mentioning the competitor) and `history[].domainSources` (source URLs — pages used for generation, not inline citations — on the competitor's own domain) are different metrics. An interactive Competitor Ranking card also renders automatically beside the answer on Apps-capable clients, in whichever shape matches the call — see below.
**Parameters:** `projectId` (required), `competitorId` (optional — ID or name; switches to the head-to-head view), `days` (default 30, max 365), `platform`, `topicId`, `unbranded`, `branded`, `country`, `locationId`, `limit` (list view, default 20, max 100), `offset` (list view) (all optional except `projectId`)
### Sources & citations
Top cited source domains from AI answers — rank, citation counts, usage %, models, and top content types. Paginated and sortable. Use to find which external sites AI models cite most; drill in with `get_source_detail`.
**Parameters:** `projectId` (required), `sort` (e.g. `"-citations"`), `limit` (default 20, max 100), `offset`, `days`, `platform`, `topicId`, `sourceType`, `unbranded`, `branded`, `country`, `locationId`, `response_format` (all optional except `projectId`)
Drill into cited sources. `level="domain"` (+ `domain`): domain summary, or `include="urls"` (cited URLs on it) / `include="responses"` (AI responses citing it). `level="url"`: with `url` → single-page citation analytics, or `include="content"` → cached page markdown + entity mentions (never triggers a live scrape); without `url` → all cited URLs across the project (optionally filtered by `contentType`).
**Parameters:** `projectId` (required), `level` (`"domain"` | `"url"`, default domain), `include` (`"urls"` | `"responses"` | `"content"`), `domain` (required for `level=domain`), `url` (`level=url`), `contentType`, `limit`, `offset`, `cursor`, `days`, `platform`, `topicId`, `sourceType`, `unbranded`, `branded`, `country`, `locationId` (all optional except `projectId`)
How the project's top source **domains** trend over time — a per-domain time-series of the external sites most used as sources in AI answers, over the window (default 30 days). An interactive Sources card renders beside the answer on Apps-capable clients: the trend line inline, expanding to the top source URLs.
**Parameters:** `projectId` (required), `days` (window; default 30 — pass `7`/`90`/`365` for a different one), `platform`, `topicId`, `sourceType`, `unbranded`, `branded`, `country`, `locationId` (all optional except `projectId`)
### Sentiment
Brand sentiment across AI platforms. `view` selects: `summary` (default) — overall score + positive/neutral/negative split + per-platform breakdown, plus `analysis` (the weekly brand-perception write-up for the platform that mentions you most, or the one you filter to with `platform`) and `analyses` (every platform's write-up); `history` — the daily sentiment trend (default 90-day window); `competitors` — head-to-head vs competitors, the brand flagged by `isBrand`. `topicId` is not accepted on `competitors`, and `compare` only on `summary`. The interactive Sentiment Profile card renders on `summary` answers only.
**Parameters:** `projectId` (required), `view` (`"summary"` | `"history"` | `"competitors"`, default summary), `days` (default 30, or 90 for `view=history`; max 365), `platform`, `topicId`, `limit` (`view=competitors`, default 10, max 50), `unbranded`, `branded`, `country`, `locationId`, `response_format` (all optional except `projectId`)
**Deprecated** — call `get_sentiment` with `view: "history"` instead (same data, same parameters). Keeps answering identically until its removal date; see [Deprecated tool names](#deprecated-tool-names).
**Parameters:** `projectId` (required), `days` (default 90, max 365), `platform`, `topicId`, `unbranded`, `branded`, `country`, `locationId`, `response_format` (all optional except `projectId`)
**Deprecated** — call `get_sentiment` with `view: "competitors"` instead (same data, same parameters). Keeps answering identically until its removal date; see [Deprecated tool names](#deprecated-tool-names).
**Parameters:** `projectId` (required), `days` (default 30, max 365), `platform`, `limit` (default 10, max 50), `unbranded`, `branded`, `country`, `locationId`, `response_format` (all optional except `projectId`)
### Query fanout
The sub-queries AI models generate when answering tracked prompts. Without `prompt_id`: the project aggregate (most frequent fanout queries, per-prompt counts, per-model stats; paginated). With `prompt_id`: every deduped sub-query for that one prompt, with per-query frequency and query type. Paid feature — returns `plan_upgrade_required` if not entitled.
**Parameters:** `projectId` (required), `prompt_id` (optional — note the snake\_case; omit for the project aggregate), `days` (default 30, max 180), `platform`, `topicId`, `unbranded`, `branded`, `limit` (aggregate, default 50, max 50), `offset` (aggregate), `topQueriesLimit` (aggregate, default 50, max 200) (all optional except `projectId`)
### Brand profile & authority
The project's knowledge-base brand profile (name, headline, category, positioning, description, topics, business type, connected entities, competitor geography/context) plus the latest batch of **AI-observed brand facts** — statements AI platforms actually make about the brand, each with its platform and verification status. Pass `include: "domain_authority"` to also get the Moz domain-authority block (latest DA/PA/spam/linking-domains snapshot + roughly-monthly 365-day history) in the same call. Call this first for brand context in any analysis. `profile` is `null` until onboarding creates one; facts come from the weekly sentiment job.
**Parameters:** `projectId` (required), `platform`, `verificationStatus` (`"unverified"` | `"pass"` | `"fail"`), `include` (`"domain_authority"`), `response_format` (all optional except `projectId`)
**Deprecated** — call `get_brand_profile` with `include: "domain_authority"` instead (same data; the REST endpoint keeps custom `days` windows). Keeps answering identically until its removal date; see [Deprecated tool names](#deprecated-tool-names).
**Parameters:** `projectId` (required), `days` (default 365, max 1095) (all optional except `projectId`)
### Prompts
The project's prompt catalog as configured — tracked prompts (type, intent, branded flag, topics, tracked locations, keyword volume/difficulty), paused (untracked) prompts, or the AI-suggested review queue (`status="suggested"` — proposals from research runs and the agent that nobody has accepted or rejected yet, each with the reason it was proposed). Configuration data, not performance — use `get_visibility group_by=prompt` for per-prompt visibility scores. The summary always reports all three counts, so pending suggestions surface from any call. An interactive Prompts card also renders automatically beside the answer on Apps-capable clients.
**Parameters:** `projectId` (required), `status` (`"tracked"` | `"untracked"` | `"suggested"` | `"all"`, default tracked), `topicId`, `limit` (default 50, max 200), `offset`, `days` (metrics window, default 30, max 365), `sortBy` (`prompt` | `volume` | `difficulty` | `branded` | `intent` | `recency`, default recency — performance columns like visibility/position/sentiment are computed per page and are **not** server-sortable), `sortDir` (`"asc"` | `"desc"`, default desc), `unbranded`, `branded`, `response_format` (all optional except `projectId`)
Raw, per-response AI-answer data for one prompt (Profound-parity) — platform, response date, response text, whether the brand was mentioned, competitors mentioned, and the source URLs the engine consulted (`sources[]` — pages used for generation, not inline citations), one entry per AI response. Not an aggregate — use `get_visibility` or `get_share_of_voice` for scores/rankings. Response text is hard-truncated at 2000 characters server-side; the markdown table shows a short snippet (120 characters, 500 in `detailed` format).
**Parameters:** `projectId` (required), `promptId` (required — note the camelCase, unlike `get_query_fanout`'s `prompt_id`), `days` (default 30, max 365), `platform`, `limit` (default 10, max 50) (all optional except `projectId` and `promptId`)
### Site health & audits
Technical + AEO site health. `view="pages"` (default) = the monitored-page inventory, **one server-paginated page at a time** (audited pages first) — every page (audited or not) with its latest technical/AEO scores, open-issue count, and last-audited date, plus `pagination.total`; page with `limit`/`offset`, filter server-side with `search` (URL/slug/title), reorder with `sortBy`, and omit the header aggregates with `includeSummary=false`; `view="audits"` = per-page technical/AEO scores for audited pages + averages; `view="issues"` = issues grouped by severity (filter `status`); `view="issue_details"` = issues grouped by type with fix guidance (filter `issueType`). An interactive Site Audit card renders beside the answer on Apps-capable clients: `pages`/`audits` show the inventory with a **search box** + **Prev/Next** paging (both server-side), a per-page **Audit** button (calls `trigger_audit` for that page), and a **Sync website** button (calls `refresh_sitemap`); `issues`/`issue_details` show the findings ranked by severity, each expanding to its fix guidance. Clicking a page row on the inventory drills into that page's own issues.
**Parameters:** `projectId` (required), `view` (`"pages"` | `"audits"` | `"issues"` | `"issue_details"`, default pages), `status` (`view=issues`: `"open"` | `"resolved"` | `"all"`, default open), `pageId` (`view=issues`: scope to one monitored page — the card's page → issues drill-down), `issueType` (`view=issue_details`: `"technical"` | `"content"`), `includeIssues` (`view=audits`, boolean), `search` (`view=pages`: server-side filter by URL / slug / title), `sortBy` (`view=pages`: `"audited"` | `"technical"` | `"aeo"` | `"issues"`, default audited-first), `includeSummary` (`view=pages`, boolean, default true), `limit` (`view=pages` default 12, max 100; `view=issues` default 1000, max 5000), `offset` (`view=pages` / `view=issues`) (all optional except `projectId`)
### Content & articles
List articles / content pieces for a project (merges content-v2 + legacy). Shows title, status, type, word count, and source.
**Parameters:** `projectId` (required), `status` (`"draft"` | `"published"` | `"editing"` | `"all"`, default all), `limit` (default 50, max 100) (all optional except `projectId`)
Full article content — HTML/markdown body, outline, FAQs, images, schema markup, internal/external links, and all metadata.
**Parameters:** `articleId` (required)
### Opportunities
Actionable opportunities Searchable surfaced for the project — prioritized fix / write / audit suggestions derived from visibility, sentiment, sources, traffic, prompts, site health, and articles. Returned in the product's priority order (status, then impact, then newest). Defaults to active opportunities; blocked for active pitch projects.
**Parameters:** `projectId` (required), `status` (`"active"` | `"completed"` | `"dismissed"` | `"auto_resolved"`, default active only), `includeResolved`, `source` (e.g. `"visibility"`, `"sentiment"`, `"sources"`, `"traffic"`, `"prompts"`, `"site_health"`, `"articles"`), `impact` (`"critical"` | `"high"` | `"medium"` | `"low"`), `limit` (default 100, max 500), `offset` (all optional except `projectId`)
### GA4 / Traffic
This tool requires a linked GA4 property. When the project has none, the backing endpoint returns a `409` error with `{ code: "ga4_not_connected", message, howToFix }` — the `howToFix` field points at **Settings → Integrations** in Searchable, where you can connect GA4 and then retry.
Google Analytics 4 website traffic. `report="ai_referrals"` (default; per-LLM-host AI Source Visitors from ChatGPT/Copilot/Gemini/Perplexity/DeepSeek and more — use for AI-referral attribution), `"trend"` (daily users/sessions/pageviews), `"top_pages"` (top landing pages by sessions), or `"sources"` (channel-group + source breakdown).
**Parameters:** `projectId` (required), `report` (`"ai_referrals"` | `"trend"` | `"top_pages"` | `"sources"`, default ai\_referrals), `weeks` (default 12, max 52), `limit` (`top_pages`/`sources`, default 20, max 100) (all optional except `projectId`)
### Search Console (GSC)
This tool requires a linked Google Search Console site. When the project has none, the backing endpoint returns a `409` error with `{ code: "gsc_not_connected", message, howToFix }` — the `howToFix` field points at **Settings → Integrations** in Searchable, where you can connect GSC and then retry.
Live Google Search Console organic performance. `report="overview"` (default): clicks/impressions/CTR/average position plus a prior-period comparison. `"top_queries"` / `"top_pages"` / `"countries"` / `"devices"`: ranked rows for that dimension. `"trend"`: daily timeseries with window totals. `"opportunities"`: quick-win queries (ranking position 4-15, ≥100 impressions, under 5% CTR). `"position_buckets"`: query-count distribution across top 3 / page 1 / page 2 / beyond 20. Pass `period` (`"7d"`|`"28d"`|`"30d"`|`"90d"`|`"16m"`, default `"30d"`) or an explicit `startDate`+`endDate` (`YYYY-MM-DD`) window — GSC data lags \~3 days.
**Parameters:** `projectId` (required), `report` (default overview), `period`, `startDate`, `endDate`, `limit` (`top_queries`/`top_pages`/`countries`/`opportunities` only; defaults 25/25/100/20) (all optional except `projectId`)
### AI Traffic
First-party AI-traffic measurement from the tracker/CDN pipeline — Searchable's flagship differentiator, distinct from GA4 above (which reads Google's own analytics). This tool requires a crawler-log, CDN, or Searchable-tracker source connected. When none is connected, the backing endpoint returns a `409` error with `{ code: "traffic_not_connected", message, howToFix }` — the `howToFix` field points at **AI Traffic → Setup** in Searchable, where you can connect a source and then retry.
First-party AI-crawler and AI-referral traffic. `report="overview"` (default): crawler + AI-referral totals by platform, plus the top crawled pages. `"crawlers"`: per-page AI-crawler activity, capped by `limit` (no deep pagination at the tool layer — use the REST endpoint's `offset` for that). `"referrals"`: daily AI-referral session timeseries by platform. `"top_cited_pages"`: top pages driving AI-referral traffic for one platform — `platform` is **required** for this report. `platform` is validated strictly, and an unrecognized value returns an error rather than a silent empty result: `crawlers` and `referrals` accept all eight platform IDs (`openai`, `anthropic`, `google`, `perplexity`, `microsoft`, `deepseek`, `xai`, `meta`), while `top_cited_pages` accepts only the first five. **`overview` ignores `platform` entirely** — it always returns every platform, so filter with `crawlers` or `referrals` instead. Long-tail vendors that can appear in *output* rows (e.g. `amazon`, `you.com`) are deliberately not filterable.
**Five further reports** cover the rest of the AI Traffic surface:
* **`sitemap_coverage`** — per bot (named, with vendor and category): how often it fetched your sitemap, how many listed pages it discovered, and the median lag from publish to first crawl. It answers how *fast and how completely* each crawler is picking your sitemap up; it does not enumerate individual uncrawled URLs.
* **`human`** — real human sessions that arrived FROM an AI assistant, split by platform. The conversion half of the funnel the crawler reports open. **Check `summarySource`:** site-wide totals come from the first-party tracker while the AI figures fall back to GA4 when no tracker is installed — in that split state every `summary` field and `percentOfTotal` are `null` (not `0`), and a failed GA4 read surfaces as `aiReferral.sourceError` rather than as zeroes.
* **`correlation`** — per page, crawls and AI-referred sessions over the **same window**, joined by path. This is co-occurrence, not attribution: nothing establishes that a session followed a crawl. Ranked by sessions, but the ranked population is the upstream union of the top-500 crawled and top-500 human-traffic pages — `pagesConsidered` is a floor, and `populationTruncated` tells you when pages are certainly missing.
* **`attribution`** — traffic by UTM tuple, referrer domain, and bot category.
* **`logs`** — the raw request feed, filterable by `path`, `statusCode`, `botsOnly`, and `host`, cursor-paginated: pass a page's `nextCursor` back as **both** `cursorTimestamp` and `cursorEventId` (half a cursor is rejected rather than silently re-serving page one). Row-capped (25 default, 100 max) because it is the one row-level report. **`ip_address` and `user_agent` are never returned** — the IP is personal data with no analytical value once `country` is present, and the user-agent is superseded by the resolved bot identity.
**`host`** narrows any report to specific hostnames (comma-separated) — useful on multi-domain projects where "blog versus docs" is the question.
**Parameters:** `projectId` (required), `report` (default `overview`), `days` (default 30, max 365), `from`/`to`, `host`, `platform` (required for `top_cited_pages`), `limit`, plus `path` / `statusCode` / `botsOnly` for `report=logs` (all optional except `projectId`)
### Shopping visibility
Requires a plan with **Shopping Analytics** (Scale or higher). `get_shopping_visibility` returns
`available: false` (not an error) when the project simply has no shopping/product data yet —
that's a data-presence state, not a plan or connection problem, and needs no setup step. The plan
gate only surfaces once there's data to fetch.
AI shopping/product visibility (Peec-parity) — products surfaced in AI shopping/product-carousel responses. `view="summary"` (default): ranked product list (rank, mentions, dominant platform) plus an activation-rate summary. `view="timeseries"`: daily activation-rate/product-count trend. Pass `productId` (the `id` from a summary row — the product's title) for full detail on one product instead: occurrences, vendor/pricing rows, a real per-platform breakdown, and up to 50 recent responses that surfaced it — `productId` overrides `view`. The `summary` view accepts the brand / topic / location filters and echoes `appliedFilters` + `availableFilters`. An interactive Shopping Shelf card also renders automatically beside the answer on the summary view for Apps-capable clients — see below.
**Parameters:** `projectId` (required), `days` (default 30, max 365), `platform`, `productId` (optional — switches to detail view), `view` (`"summary"` | `"timeseries"`, default summary), `limit` (summary view, default 50, max 100), `offset` (summary view), `topicId`, `unbranded`, `branded`, `country`, `locationId` (all optional except `projectId`)
### AI ads
Ad data appears once tracked prompts surface sponsored ad units. An empty result means either that
nothing has been captured yet **or** that a filter didn't resolve — `topicId`, `locationId` and
`promptId` take IDs, not names. An unrecognized value is dropped from its filter; only when none
of a filter's values resolve does that filter match nothing rather than being ignored — a mixed
list silently returns just the recognized subset. Retry without filters before reporting that a
project has no ad data, and state that the retried figures are unfiltered. `adCount`/`appearances`
count ads we scraped in AI answers, not ad-platform impressions, and commercial ad libraries don't
publish spend, so there are no cost or impression figures.
Sponsored ads surfaced in AI answers. `view="advertisers"` (default): who is running ads, ranked by ad volume with share % and a competitor flag, plus your own brand's ad share-of-voice and rank. `view="creatives"`: the individual ad creatives (advertiser, headline, appearances, prompts) — narrow with `advertiserKey`, `promptId`, or `search`. `view="prompts"`: which tracked prompts surface the most ads, with ad coverage %. `view="timeseries"`: per-advertiser ad-frequency trend.
**Parameters:** `projectId` (required), `view` (`"advertisers"` | `"creatives"` | `"prompts"` | `"timeseries"`, default advertisers), `days` (default 30, max 365), `filter` (`"all"` | `"competitors"`, view=advertisers), `advertiserKey` (view=creatives/timeseries), `promptId` + `search` (view=creatives), `sortBy` (`promptText`|`adUnits`|`coveragePct`|`engines`|`totalResponses`, default adUnits) + `sortDir` (view=prompts), `limit` (advertisers default 20/max 100, creatives 25/200, prompts 50/500), `platform`, `topicId`, `locationId`, `unbranded`, `branded`, `response_format` (all optional except `projectId`)
### Write actions
All three require a grant/key with the **write** scope. None of them execute without `confirm:
true` — omit it and the tool returns a dry-run preview (what would happen, current quota state)
with no side effect.
Generate + publish a shareable report and return its public URL. `reportType`=`sentiment`|`visibility`|`combined` (default sentiment). Note the `Only` suffix on the brand filters here — `unbrandedOnly`/`brandedOnly` — unlike every read tool's `unbranded`/`branded`.
**Parameters:** `projectId` (required), `reportType`, `timeRange` (`"7d"`|`"30d"`|`"90d"`|`"365d"`, default 30d), `platforms`, `topicIds`, `locationIds`, `unbrandedOnly`, `brandedOnly`, `title`, `status` (`"published"`|`"draft"`, default published), `whiteLabel` (requires a white-label-entitled plan), `confirm` (all optional except `projectId`)
Start a technical + AEO site audit for the project's pages (all tracked pages by default, or the given `pageIds`); returns the job id. Results land on `get_site_health` (`view="audits"`). Consumes the monthly audit quota and is blocked for pitch projects.
**Parameters:** `projectId` (required), `pageIds` (optional — omit to audit every tracked page), `confirm` (optional)
Re-sync the project's configured sitemap — re-discovers it and reconciles monitored pages (add/update/remove) in the background; returns the job id. Read the result with `get_site_health` (`view="pages"`). Blocked for pitch projects.
**Parameters:** `projectId` (required), `confirm` (optional)
### Removed tool names
Earlier iterations of this MCP shipped 35 individual tools. When those were consolidated, 26 of the old names stayed callable as deprecated aliases. **Those aliases were removed in August 2026** — calling one of the names below now returns an unknown-tool error. Use the replacement.
| Removed tool | Use instead |
| ----------------------------- | ------------------------------------------------------------- |
| `get_visibility_summary` | `get_visibility` (`group_by: "summary"`) |
| `get_visibility_details` | `get_visibility` (`group_by: "platform"`) |
| `get_visibility_by_topic` | `get_topic_analysis` |
| `get_visibility_by_prompt` | `get_visibility` (`group_by: "prompt"`) |
| `get_visibility_by_location` | `get_visibility` (`group_by: "location"`) |
| `get_prompt_topics` | `get_topic_analysis` |
| `get_sources` | `search_sources` |
| `get_source_domain` | `get_source_detail` (`level: "domain"`) |
| `get_source_domain_urls` | `get_source_detail` (`level: "domain", include: "urls"`) |
| `get_source_domain_responses` | `get_source_detail` (`level: "domain", include: "responses"`) |
| `get_source_urls` | `get_source_detail` (`level: "url"`) |
| `get_source_page` | `get_source_detail` (`level: "url"`, with `url`) |
| `get_source_page_content` | `get_source_detail` (`level: "url", include: "content"`) |
| `get_source_content_types` | `get_source_trends` (`breakdown: "content-types"`) |
| `get_source_types` | `get_source_trends` (`breakdown: "source-types"`) |
| `get_source_article_types` | `get_source_trends` (`breakdown: "article-types"`) |
| `get_source_trend` | `get_source_trends` (`breakdown: "trend"`) |
| `get_prompt_query_fanout` | `get_query_fanout` (use `prompt_id`, not `promptId`) |
| `get_ga4_ai_referrals` | `get_ga4_traffic` (`report: "ai_referrals"`) |
| `get_ga4_traffic_trend` | `get_ga4_traffic` (`report: "trend"`) |
| `get_ga4_top_pages` | `get_ga4_traffic` (`report: "top_pages"`) |
| `get_ga4_traffic_sources` | `get_ga4_traffic` (`report: "sources"`) |
| `get_website_issues` | `get_site_health` (`view: "issues"`) |
| `get_page_audits` | `get_site_health` (`view: "audits"`) |
| `get_monitored_pages` | `get_site_health` (`view: "pages"`) |
| `get_issue_details` | `get_site_health` (`view: "issue_details"`) |
Nine other pre-consolidation names kept their exact original name as a primary tool at the time. Six still do — `list_projects`, `list_articles`, `get_article`, `get_opportunities`, `get_sentiment`, and `get_query_fanout`; the other three (`get_visibility_history`, `get_sentiment_history`, `get_sentiment_competitors`) were folded into selector views in August 2026 and are now deprecated names — see the next section.
The four `get_source_*` breakdown rows above are the one case where the removed name did something
no MCP tool now does: `breakdown` (and `get_source_trend`'s `group`) were arguments only those
aliases accepted. `get_source_trends` returns the top-source-domain trend directly and has no
`breakdown` argument. For the content-type, source-type, or article-type breakdown, use the [REST
endpoint](/advanced/api-usage).
### Deprecated tool names
The August 2026 family-grid consolidation folded four reads into selector parameters on their
family's primary tool. Unlike the removed aliases above, these four names **still work** — same
handler, byte-identical payload — so existing scripts and scheduled jobs keep running. They are
scheduled for removal **after 2026-10-15** (the same \~60-day window the removed aliases got);
move to the replacement call before then. The REST endpoints behind these reads
(`GET /visibility/history`, `GET /sentiment/history`, `GET /sentiment/competitors`,
`GET /domain-authority`) are **not** deprecated — the [12-month REST deprecation
policy](/changelog#deprecation-policy) governs those, and nothing REST-side is scheduled for
removal.
| Deprecated name | Use instead |
| --------------------------- | --------------------------------------------------- |
| `get_visibility_history` | `get_visibility` (`group_by: "date"`) |
| `get_sentiment_history` | `get_sentiment` (`view: "history"`) |
| `get_sentiment_competitors` | `get_sentiment` (`view: "competitors"`) |
| `get_domain_authority` | `get_brand_profile` (`include: "domain_authority"`) |
## Interactive cards
Nine tools render an interactive card beside their answer in **MCP-Apps-capable hosts** (Claude
web/desktop, ChatGPT, Goose, VS Code — all implement the same standard):
| Tool | Card | What it shows |
| ------------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `get_visibility` | **Visibility Snapshot** | Score, trend, and per-platform bars, with brand/topic/location controls in fullscreen |
| `get_share_of_voice` | **Share of Voice** | Your own share as a headline number, its movement, and bars showing where the rest of the share sits |
| `get_competitors` | **Competitor Ranking** | List call → brand + competitors in one ranked table; `competitorId` call → the head-to-head split comparison |
| `get_sentiment` | **Sentiment Profile** | Model selector across engines, the selected engine's brand-perception write-up, and its positive/neutral/negative |
| `get_topic_analysis` | **Topic Analysis** | A visibility bar per topic, expandable to that topic's strengths, gaps, and top rival |
| `get_source_trends` | **Sources** | Top-domains citation-trend chart, expanding to the cited-URLs table |
| `get_site_health` | **Site Audit** | Server-paginated page inventory with search + per-page **Audit** and **Sync website** buttons, or ranked findings |
| `list_prompts` | **Prompts** | Compact prompt table inline; full metrics table with topic/branded filters and sortable columns in fullscreen |
| `get_shopping_visibility` | **Shopping Shelf** | Product image, title, price, rating, and platform (summary view only) |
`get_visibility` hides its card on a `platform`-filtered call and on `group_by=prompt|location`,
where the card's numbers would misrepresent the answer. Hosts without MCP Apps support just see the
normal text/JSON answer. Cards are dark/light aware and have an Expand button for a fullscreen view.
Where a card has a period control you switch window inside the card rather than sending another
message — the card queries the tool itself and remembers each window it has already loaded, so
returning to one is instant.
## Pagination
Tools that return lists are paginated so you can read complete datasets without silent truncation.
### Per-prompt visibility
`get_visibility` with `group_by: "prompt"` is fully paginated (the deprecated `get_visibility_by_prompt` alias maps to the same call). Every response includes a `pagination` object that tells you whether more prompts exist and exactly how to fetch the next page:
```json theme={null}
{
"pagination": {
"limit": 100,
"offset": 0,
"returnedCount": 100,
"totalCount": 740,
"hasMore": true,
"nextOffset": 100
}
}
```
Loop until you've read every prompt:
1. Call `get_visibility` with `group_by: "prompt"` (defaults: `limit` 100, `offset` 0).
2. While `pagination.hasMore` is `true`, call again with `offset` = `pagination.nextOffset`.
3. Stop when `pagination.hasMore` is `false`.
`limit` accepts 1–500 prompts per page. The total number of prompts you can page through is unbounded — paging in fixed-size chunks scales to projects with thousands of prompts.
### Other list tools
Other list-returning tools paginate too: `get_opportunities`, `search_sources`, `get_source_detail` (`include: "responses"`), and `get_query_fanout` (per-prompt list) use `limit` + `offset`, while `get_source_detail` (`include: "urls"`, or `level: "url"` for the flat cross-project listing) is cursor-based (pass the `cursor` from the previous response until none is returned). `get_prompt_answers` also returns the standard `limit`/`offset`/`hasMore`/`nextOffset` pagination shape, but the tool layer only exposes `limit` (max 50) — use the REST endpoint's `offset` for deep pagination.
## Example prompts
### Visibility analysis
```
What's my brand's AI visibility score for the last 30 days?
```
```
How does my brand perform on ChatGPT vs Claude vs Perplexity?
```
```
Which topics have the weakest visibility? Show me the top 5.
```
### Site audit
```
What critical AEO issues does my site have and how do I fix them?
```
```
Show me the pages with the lowest AEO scores.
```
### Content
```
List all my draft articles.
```
```
Get the full content of my latest published article for review.
```
## Use cases
### Automated issue fixing
Pair the MCP with a coding assistant to retrieve AEO/SEO issues and apply fixes in your codebase:
```
Get all critical issues for my project and propose fixes in this repo
```
The assistant fetches issues from Searchable (missing meta descriptions, alt text, heading structure, etc.), locates the relevant files, and proposes or applies fixes.
### For developers
* Query AEO/SEO issues while debugging frontend code
* Check if code changes would impact page audit scores
* Review article content without leaving your IDE
### For AEO/SEO teams
* Pull visibility summaries during standups
* Extract audit data for reports
* Track issue resolution progress
### For content teams
* Review article status and metadata
* Pull full article content for editing
* Track content coverage across topics
## Troubleshooting
* Confirm the server URL is exactly `https://app.searchable.com/api/mcp-server/mcp` (browser-sent `Origin` headers are validated against an allowlist — hosted connectors normally call server-side without one, so they're unaffected).
* Check your API key starts with `sea_` and is enabled for MCP in Searchable settings.
* Restart your MCP client after config changes.
* Make sure you're logged in to Searchable in the same browser, then retry the connection from
your client. - The authorization link is single-use and expires after a few minutes — if you left
it open, restart the connection from your client to get a fresh one. - On the consent screen,
select at least one project (or leave all selected) before clicking **Authorize**.
* Confirm the key starts with `sea_` and hasn't been revoked in **Settings → Integrations**. -
Confirm the key's workspace is on a paid Searchable plan — MCP is unavailable on the Free plan.
* Confirm you have projects in your Searchable account. - Check that the API key belongs to the
correct workspace.
* The project has no GA4 property linked, so the tool call returns a `409` error with `code:
"ga4_not_connected"`. - Connect Google Analytics 4 under **Settings → Integrations** in your
Searchable dashboard (the error's `howToFix` field carries the direct link), then retry the tool
call.
* The project has no Google Search Console site linked, so the tool call returns a `409` error
with `code: "gsc_not_connected"`. - Connect Google Search Console under **Settings →
Integrations** in your Searchable dashboard (the error's `howToFix` field carries the direct
link), then retry the tool call.
* The project has no crawler-log, CDN, or Searchable-tracker source connected, so the tool call
returns a `409` error with `code: "traffic_not_connected"`. - Connect a source under **AI Traffic
→ Setup** in your Searchable dashboard (the error's `howToFix` field carries the direct link),
then retry the tool call.
* The workspace's plan doesn't include **Shopping Analytics** (Scale or higher), and the project
has shopping data to fetch, so the tool call returns a `403`-equivalent error with `code:
"plan_upgrade_required"`. - This is different from `available: false` — that's a normal 200
response meaning the project just has no shopping data yet, not a plan restriction. If you're
seeing `available: false` instead of this error, no upgrade is needed. - Upgrade to a plan with
Shopping Analytics in **Settings → Billing**, then retry.
Both are retryable, and neither means you've exhausted a quota. `rate_limited` means another heavy
read for the **same project** is still running — the limit is per project, not per key, so wait a
moment and retry, and avoid firing many project-wide tools in parallel for one project.
`query_timeout` means the aggregation ran past the server-side limit — reduce the `days` window or
add filters (`platform`, `topicId`, `country`), then retry.
* The connected grant or API key only has **read** access. Write tools require the **write**
scope. - Re-authorize with **Read & write** selected on the consent screen, or create/edit an API
key with read-and-write access in **Settings → Integrations**.
* Restart your MCP client.
* Verify the server URL and JSON config syntax.
* Check the client's MCP logs for errors.
## Security
### Read-only by default, write tools scope-gated
Every tool except the 3 write tools is annotated `readOnlyHint: true`: they can only list and read data. The 3 write tools (`generate_report`, `trigger_audit`, `refresh_sitemap`) additionally require a grant or key with the **write** scope, and each still needs an explicit `confirm: true` on the individual call before it does anything — a read-only connection can't invoke them at all (the call fails with `missing_scope`), and even a read-and-write connection gets a no-op dry-run preview until it passes `confirm: true`.
### Token & key handling
* The OAuth login flow issues your client an access token scoped to exactly the projects and read/write access you approved on the consent screen — no API key is created or stored for this path.
* Every request is re-checked against the server-side authorization grant, so a revoked grant stops working immediately — the token in the client's hands can't outlive the consent it came from.
* Tokens refresh silently while the connection is in use; active connections persist, and an idle connection expires about 60 days after its last use, after which you simply re-authorize.
* On the legacy API-key path, the `sea_` key **is** the bearer token — treat it as a secret, scope it narrowly, and revoke it in **Settings → Integrations** if it's exposed.
### Origin validation
The server validates browser `Origin` headers against an allowlist (`claude.ai`, `claude.com`, plus dev hosts) to prevent cross-site abuse. Requests without an `Origin` header are allowed through — that covers native clients (Claude Desktop, Cursor, curl) **and** hosted connectors like Claude.ai and ChatGPT, which call from their servers rather than a browser. This is defense-in-depth; bearer-token auth is the primary control.
### Best practices
* **Rotate keys regularly** — generate new keys periodically and revoke old ones.
* **Use per-use-case keys** — separate keys for separate clients makes revocation targeted.
* **Revoke unused keys** — remove keys you're no longer using from Searchable settings.
## API reference
### Server details
| Property | Value |
| -------------- | ------------------------------------------------------- |
| Endpoint | `https://app.searchable.com/api/mcp-server/mcp` |
| Transport | Streamable HTTP |
| Protocol | MCP 1.0 |
| Authentication | OAuth 2.1 + PKCE, Client ID Metadata Documents, and DCR |
### Rate limits
Searchable does not enforce a per-key request-rate limit today, but two server-side controls can make a call fail retryably:
* **Per-project concurrency.** Heavy aggregation reads take a per-project lock, so a second heavy call for the same project while the first is still running is rejected rather than queued. On the REST API that's a `429` with a `Retry-After` header; MCP tools have no header channel, so the tool returns the error code `rate_limited` with retry guidance in `howToFix`. Wait a moment and retry — the limit is per project, not per key.
* **Query timeout.** Long aggregations are bounded by a server-side timeout, returning `query_timeout` with a hint to narrow the `days` window or add filters.
Both are retryable. Normal interactive usage from Claude, Cursor, or similar clients is not expected to hit either; parallel fan-out across many tools for the same project is the usual trigger.
## Support
Browse the integrations directory
Email our team
# Integrations Overview
Source: https://docs.searchable.com/integrations/overview
Connect Searchable with your favorite tools and platforms
## Available Integrations
Searchable connects with popular platforms to enrich your data and streamline your workflow.
Connect to Cursor, Claude Code, and Windsurf
SEO performance data and keyword insights
Traffic analytics and user behavior data
## Integration Benefits
### Data Enrichment
Combine Searchable's AI visibility data with:
* **GSC**: See which keywords drive both traditional search and AI visibility
* **GA4**: Understand user behavior and conversion from AI-referred traffic
* **CMS**: Seamlessly publish optimized content
### Workflow Automation
* Publish content directly from Searchable to your CMS
* Sync SEO metadata automatically
* Trigger audits on content updates
* Automate reporting with integrated data
### Unified Analytics
* Single dashboard for SEO, AEO, and analytics
* Cross-channel attribution
* Comprehensive performance tracking
* Correlation between AI visibility and traffic
## Integration Categories
### Analytics & Performance
**What it does:**
* Syncs keyword rankings and impressions
* Shows CTR and position data
* Identifies technical issues
* Tracks search performance
**Benefits for Searchable:**
* Correlate traditional SEO with AI visibility
* Identify high-value keywords for prompt optimization
* Track both Google and AI platform performance
* Unified keyword strategy
**Plan Availability:** Professional, Agency, Custom
**What it does:**
* Tracks website traffic and user behavior
* Measures conversions and goals
* Provides audience insights
* Shows traffic sources
**Benefits for Searchable:**
* Measure AI-referred traffic
* Calculate ROI of AI visibility efforts
* Identify high-converting AI prompts
* Track user journeys from AI platforms
**Plan Availability:** Professional, Agency, Custom
## Setup Process
Most integrations follow this flow:
Go to Settings → Integrations in your project
Click on the integration you want to add
Grant Searchable necessary permissions
Set sync preferences and automation rules
Run a test sync to verify connection
Most integrations connect in under 5 minutes. Detailed guides are available for each platform.
## Integration Comparison
| Integration | Plan Required | Setup Time | Data Sync | Publishing | Best For |
| --------------------- | ------------- | ---------- | --------- | ---------- | ------------------- |
| MCP (AI Assistants) | Starter+ | 2 min | Real-time | No | Developer workflows |
| Google Search Console | Pro+ | 2 min | Hourly | No | SEO correlation |
| Google Analytics 4 | Pro+ | 3 min | Real-time | No | Traffic analysis |
## Security & Permissions
### Data Access
Searchable only requests minimum necessary permissions:
* **Read access**: To retrieve data for analysis
* **Write access**: Only when publishing content (you control this)
* **No deletion**: We never delete your data
### Authentication
All integrations use secure OAuth 2.0 or API key authentication:
* Tokens encrypted at rest
* Automatic token refresh
* Revocable anytime
* Audit logs (Custom)
### Data Privacy
* Data processed in compliance with GDPR and CCPA
* No data sold to third parties
* Stored securely with encryption
* You own all your data
When disconnecting an integration, synced data is preserved but no new data is imported.
## Managing Integrations
### Connected Integrations
View all active integrations in Settings → Integrations:
* **Status**: Active, Error, Syncing
* **Last Sync**: Timestamp of most recent sync
* **Data Preview**: Sample of synced data
* **Actions**: Disconnect, Reconnect, Configure
### Sync Settings
Configure sync behavior:
* **Frequency**: How often to sync data
* **Scope**: What data to include/exclude
* **Notifications**: Alerts for sync issues
* **Automation**: Trigger actions on sync
### Troubleshooting
Common integration issues:
* Verify account permissions
* Check for expired tokens
* Try disconnecting and reconnecting
* Clear browser cache
* Check sync schedule
* Verify data exists in source
* Review scope settings
* Check for API rate limits
* Verify write permissions
* Check CMS is accessible
* Review field mapping
* Test with simpler content
## Custom Integrations
Custom integrations available for Custom customers:
* **Salesforce**: CRM integration for attribution
* **HubSpot**: Marketing automation sync
* **Slack**: Team notifications and alerts
* **Zapier**: Connect to 1000+ apps
* **Custom APIs**: Build proprietary integrations
Contact [support@searchable.com](mailto:support@searchable.com) for Custom integrations.
## Coming Soon
Integrations in development:
* Shopify (E-commerce)
* Squarespace (Website builder)
* Ghost (Publishing platform)
* Notion (Documentation)
* Make.com (Automation)
Vote on your favorites at features.searchable.com.
## Integration Support
Need help with integrations?
Detailed guides for each platform
Watch setup walkthroughs
Contact our integration specialists
Build custom integrations
## Next Steps
Connect GSC for keyword data
Track traffic and conversions
# Introduction
Source: https://docs.searchable.com/introduction
Welcome to Searchable - AI-powered SEO platform for the future of search
## Welcome to the Searchable Docs!
Searchable is an AI-powered SEO and AEO (Answer Engine Optimization) platform that helps businesses improve their visibility in both traditional search engines and AI-powered platforms like ChatGPT, Claude, and Perplexity.
As search evolves, your strategy must too. This documentation covers everything you need to master both traditional SEO and the emerging world of AI visibility.
### What is AEO?
Answer Engine Optimization (AEO) is the practice of optimizing your content to be cited and recommended by AI models. When someone asks ChatGPT "What's the best CRM for startups?", will your brand be mentioned? That's AEO.
### Platform Capabilities
Monitor brand mentions across 9 AI platforms with prompt-based tracking
Comprehensive technical, content, and AEO audits with actionable recommendations
Generate SEO and AEO-optimized content that ranks in Google and gets cited by AI
Connect GSC and GA4 for seamless workflows
### Documentation Structure
This documentation is organized to take you from beginner to expert:
**Getting Started**: Set up your account, create projects, and understand the dashboard\
**Using Searchable**: Master scores, prompts, content, and audits\
**Integrations**: Connect your tools and platforms\
**Advanced Features**: AI Copilot, teams, and API access
### Quick Links
Get up and running in 5 minutes
Learn what your scores mean
Master AI visibility tracking
Find the right plan for you
Connect your tools
Build custom integrations
# Quickstart
Source: https://docs.searchable.com/quickstart
Get up and running with Searchable in under 5 minutes
## Setup your account
You can set up your account by following [this link](https://app.searchable.com/onboarding). If this is your first time using Searchable, you'll need to complete a simple onboarding form, at the end of which you'll have your first domain all set up!
To complete the setup quickly and easily, make sure you've got this information on hand:
* Your details - name, email that you have access to
* Location of your business - city & country
* Your brand's reach - worldwide, nationwide, or narrower
* Your target website (e.g. yourwebsite.com) that you want to analyse
* 1-5 of your main competitors
## Adding your first domain
Your first domain will be created as part of the onboarding - no additional actions required!
## Run your first audit
Searchable's audit system provides comprehensive analysis of your site's SEO and AEO performance.
As soon as you set up your domain, Searchable will automatically fetch every page of your website using your sitemap. You'll be able to see the full list of URLs in the On-Page > Site Health section of the platform.
Connecting your Google Analytics 4 will allow you to prioritize pages based on traffic they generate.
### Site Audit Features
Analyze page speed, mobile-friendliness, and technical optimization
Check how well your content performs in AI-powered search results
Evaluate content structure, readability, and keyword optimization
Assess internal and external link structure and quality
### Understanding Your Results
Your audit results are organized into several key areas:
* **Overall Score**: A comprehensive score from 0-100 based on all factors
* **Technical Issues**: Critical issues that need immediate attention
* **Content Recommendations**: Suggestions for improving content quality
* **AI Optimization**: Specific recommendations for better AI visibility
Start with fixing critical technical issues first, as they have the biggest impact on your overall performance.
## Set up integrations
Connect Searchable with your existing tools and platforms to streamline your workflow.
### Popular Integrations
Connect GSC for keyword data and SEO insights
Track traffic and conversions from AI platforms
See all available integrations
### Setting up your first integration
1. Navigate to **Manage Account** → **Integrations**
2. Choose your platform from the available options
3. Follow the platform-specific setup guide
4. Authenticate and grant necessary permissions
5. Configure sync settings and automation rules
Start with Google Search Console and Google Analytics 4 for the richest data insights. You can also add them in your Analytics > Traffic tab.
## Set up your Knowledge Base
Knowledge Base is how you tell the Searchable Agent all about your brand voice, writing style, and content preferences.
### Brand Snapshot
Your brand in a nutshell. We will automatically generate an overview of your brand from your website, but you can always amend it or add additional instructions and files.
### Voice & Style
Your brand's voice is unique, so let's make sure that is reflected in your content. Set the tone, writing complexity and preferred terms.
### Competitors
Competitors won't only show up in your Visibility reports, but also inform what content gaps you have in comparison. We will automatically suggest some, but you can always amend the list.
### Terminology
Define terms, products and use cases that matter the most, so that they are highlighted in your content.
### Compliance
Add disclaimers, regulatory guardrails and restricted claims. Saves time for you and your legal team!
Always double-check generated content with claims and disclaimers. AI can make mistakes.
## Generate your first content
Use Searchable's AI-powered content generation to create optimized articles.
### Content Generation Process
Select from blog posts, landing pages, or custom content types
Let the Agent know what kind of post you'd like to write. This can be as simple or detailed as you'd like.
Our AI analyzes current trends, competitor content, and search patterns
AI will create the article outline. Feel free to add, delete or tweak any of the sections to create the best article.
AI creates optimized content with proper citations and structure
Review the generated content and publish directly to your platform
## Check your current performance
See how your website performs right now.
### Key Metrics to Watch
* **Brand Visibility Score**: How often your brand appears in AI search results
* **Content Performance**: Which articles drive the most AI visibility
* **Technical Health**: Overall site performance and SEO score
* **Competitive Position**: How you compare to industry competitors
Access your real-time analytics dashboard
## Next Steps
Now that you're set up, explore these guides to master Searchable:
Learn what your Technical, Content, and AEO scores mean
Master AI visibility tracking with effective prompts
Create AI-optimized content that gets citations
Invite team members and collaborate effectively
### Additional Resources
* **[Plans & Pricing](/getting-started/plans-pricing)**: Upgrade for advanced features
* **[Integrations Guide](/integrations/overview)**: Connect all your tools
* **[Troubleshooting](/using-searchable/troubleshooting)**: Solutions to common issues
Join our [Slack community](https://join.slack.com/t/searchablecommunity/shared_invite/zt-3d72toig3-5CNPzd1ujFQu_IanWGTHDA) to connect with other users and get tips from SEO experts.
# Send Akamai traffic to Searchable (DataStream 2)
Source: https://docs.searchable.com/setup/akamai-datastream2
Configure an Akamai DataStream 2 stream to push request logs to Searchable over HTTPS. No code changes — all configuration is done inside Akamai Control Center.
## What this does
Akamai [DataStream 2](https://techdocs.akamai.com/datastream2/docs/welcome-datastream) ships near-real-time request logs from your Akamai properties to a destination of your choosing. We point that stream at Searchable's tracker endpoint, classify the AI bots at the edge, and drop everything else. No code changes — all configuration happens inside Akamai Control Center.
**No code changes.** All configuration is done inside Akamai Control Center.
## Prerequisites
An Akamai account with **DataStream 2** entitled on the contract that owns your delivery property
The **Edit** role on that property, or an Akamai admin who can author and activate a stream
A Searchable project with your domain confirmed
DataStream 2 is a per-contract product. If the **DataStream** entry doesn't appear in Control
Center, your Akamai contract doesn't include it yet — your Akamai account team can add it. The
legacy DataStream 1 product is not supported by this integration; you need DataStream 2 (the
JSON-format successor).
## Setup
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Akamai** as your crawler source
4. Click **Generate token**
Copy the token now — it starts with `sa_…` and won't be shown again. You can always generate a new one if you lose it.
The endpoint URL is fixed:
```
https://tracker.searchableanalytics.com/v1/akamai-logs
```
Sanity check before pointing DataStream at the endpoint:
`curl https://tracker.searchableanalytics.com/v1/akamai-logs` should return `200 ok`. That's the same health check Control Center's **Validate and save** step runs against the URL when you finish the wizard.
In Akamai Control Center, navigate to:
**CDN → DataStream → Create new stream**
Give the stream a name like `Searchable LLM Analytics` and assign it to the group that contains the property fronting your domain. Pick the **property** that serves the traffic you want Searchable to see — DataStream is scoped per-property, not per-account.
If your domain is fronted by more than one property (for example, `www` and `api` on separate properties), create one stream per property and point them all at the same endpoint with the same token. Searchable tags events by host, so they still arrive split by domain in the dashboard.
Before picking fields, set the log format. On the **Data sets** step, look near the top for **Log file format** and set it to **Structured JSON**.
**"JSON" and "Structured JSON" look almost identical in the dropdown — pick Structured JSON.** Only Structured JSON emits one record per line (NDJSON), which is what our endpoint ingests. Choosing plain **JSON** is the single most common cause of a stream that delivers successfully on Akamai's side but produces no events in Searchable.
Still on the **Data sets** step, select the fields below. Field names are case-sensitive — note `UA` is capitalised (it is **not** `reqUserAgent`), and the sub-country admin region is `state` (not `region`).
Select all of these:
* `reqID`
* `reqMethod`
* `reqHost`
* `reqPath`
* `UA` *(capital — not `reqUserAgent`)*
* `statusCode`
* `cliIP`
* `reqTimeSec`
* `reqEndTimeMSec`
Of those, the endpoint **drops any record** missing `reqID`, `reqMethod`, `reqHost`, `reqPath`, `UA`, `statusCode`, `cliIP`, or `reqTimeSec`. `reqEndTimeMSec` is optional in the strict sense — a record without it is still ingested — but tick it anyway: it's what populates response time in your dashboard.
Recommended additions (used for enrichment + debugging; missing fields don't break the integration):
* `queryStr`
* `referer` *(HTTP-standard single-r spelling)*
* `rspContentLen`
* `turnAroundTimeMSec` *(time-to-first-byte in ms)*
* `cacheStatus`
* `country`
* `state`
* `city`
* `edgeIP`
* `tlsVersion`
The exact list, comma-separated for quick copy/paste, is also shown in the Searchable setup card.
In Structured JSON, Akamai emits the request-ID field as `reqId` (lowercase `d`) and all numeric values as JSON strings. Searchable accepts either casing (`reqID` or `reqId`) and coerces the strings, so you don't need to do anything special on your end — just tick the field as Control Center labels it.
After changing the format or the field selection, confirm your fields are still ticked and **save** — switching the log file format can reset the selection.
`reqID` is load-bearing and required. DataStream 2 has at-least-once delivery semantics, so the same record can arrive in multiple batches; Searchable derives a stable event ID from `reqID` to deduplicate them. Records without it are dropped.
**`reqTimeSec` vs `reqEndTimeMSec`**: despite the suffix, `reqEndTimeMSec` is a *duration* (how long the request took, in ms), not a wall-clock value. The actual epoch timestamp is `reqTimeSec` (epoch seconds). Searchable uses `reqTimeSec` for the event time and `reqEndTimeMSec` for `response_time_ms` — both fields are useful and we capture both when present.
On the **Delivery** step, choose **HTTPS** and fill in:
| Field | Value |
| ------------------------------ | -------------------------------------------------------- |
| **Endpoint URL** | `https://tracker.searchableanalytics.com/v1/akamai-logs` |
| **Authentication** | None |
| **Custom HTTP header — name** | `X-Searchable-Token` |
| **Custom HTTP header — value** | `` *(no `Bearer ` prefix)* |
| **Compress files** | Off *(see note below)* |
**Use `X-Searchable-Token`, not `Authorization` — and do not prefix the value with `Bearer `.** Paste the raw `sa_…` token as the header value, with no prefix, no space, and no quotes.
Set **Authentication** to **None** and put the token in a **custom header**. Akamai's built-in Authentication choices (Basic, mTLS) are for upstreams that expect those formats — Searchable verifies its own signed token, so the right slot is a plain custom header.
DataStream 2's HTTPS delivery sends batched, line-delimited JSON. Searchable's endpoint accepts both uncompressed and gzip-compressed bodies. If you turn on **Compress files**, leave the rest of the settings unchanged — Akamai sets `Content-Encoding: gzip` automatically and our endpoint decompresses on the way in.
On the **Frequency** step, choose **30 seconds** (the default) or **60 seconds**. Either is fine — both keep dashboard latency under a minute.
Don't choose the largest "files per group" / longest interval option. Larger Akamai batches are still well under our 5 MB payload cap on any realistic traffic level, but tighter intervals give you faster feedback in the dashboard while debugging.
On the **Review** step, click **Validate and save**. Akamai sends a `GET` to the endpoint URL and expects a `200` response — Searchable's tracker responds with a literal `ok`. If validation fails, see [Troubleshooting](#troubleshooting) below.
Once validation succeeds, click **Activate**. Akamai activation typically completes within a couple of minutes on Staging and 5–10 minutes on Production. Once active, expect events in Searchable as soon as an AI bot hits your site.
## Verifying the connection
In Searchable:
1. Go to **LLM Analytics → Setup**
2. Look at the Akamai card status
3. Click **Check** if it still shows "Waiting for first event"
| Status | What it means |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **Waiting for first event** | The stream is configured but no AI bot has hit your site yet. Typical wait is a few hours for sites that are already indexed. |
| **Connected** | Events are arriving. The card shows the count from the last 24 hours. |
You can also confirm in Akamai: **CDN → DataStream → your stream → Monitor**. The stream's metrics show outgoing batches and the HTTP response codes from our endpoint. Healthy delivery looks like a steady stream of `204` responses.
## What Searchable receives
For each request that matches an AI-bot user agent, Searchable receives:
* HTTP method, path, and host (query strings stripped before storage)
* User agent
* Referer
* Country, state, and city (from `country` / `state` / `city`)
* Response status and bytes out (`rspContentLen`)
* Edge turnaround time (`turnAroundTimeMSec`)
* Akamai edge metadata (`edgeIP`, `tlsVersion`, `cacheStatus`) — preserved as `custom_properties` for debugging
* The DataStream 2 `reqID` — used as the dedup key on our side
Bodies, headers other than `User-Agent` / `Referer`, cookies, and full IPs are never sent or stored. The DataStream 2 `reqID` is hashed into a deterministic event ID so retried batches collapse into a single event server-side.
## Troubleshooting
Akamai's validator does a `GET` against your endpoint URL and expects `200`. The two common reasons it fails:
* **Typo in the URL** — the correct value is exactly `https://tracker.searchableanalytics.com/v1/akamai-logs`. No trailing slash, no path suffix.
* **A custom Akamai delivery network policy** is blocking egress to `tracker.searchableanalytics.com`. In strict environments this surfaces as a connection error rather than a 4xx. If you suspect this, ask your Akamai admin to allow-list that hostname for the delivery property.
The custom header isn't validated at this step — Akamai's `Validate and save` only verifies that the URL is reachable. Auth issues surface in the **Monitor** tab after the stream activates.
The token header is missing or wrong.
* Make sure you added a **custom HTTP header** named exactly `X-Searchable-Token`
* The value must be the **raw `sa_…` token with no `Bearer ` prefix**, no quotes, and no leading or trailing space. A value of `Bearer sa_…` will fail — paste the token on its own
* Confirm the **Authentication** dropdown is set to **None** — picking **Basic** there overrides the custom header
* If you've recently revoked the token in Searchable, generate a new one and update the stream's custom header (no need to recreate the stream)
In Akamai's **Monitor** tab, repeated `401` responses are the visible symptom — fix the header and the next batch will succeed. A `403` instead means the header arrived but the token failed signature verification: it's truncated, from a different environment, or has been revoked.
Map the response code to the cause:
* **`401 Unauthorized`** — the token header is missing or malformed; see the section above.
* **`403 Forbidden`** — the header arrived but the token failed verification (truncated, revoked, or from a different environment).
* **`413 Payload Too Large`** — the batch exceeded Searchable's 5 MB payload cap. This is rare on default frequency settings (30s / 60s); if you see it, lower the upload interval rather than raising file sizes.
While 4xx errors are occurring, Akamai retries each batch a few times and then drops it. Fix the root cause and the stream catches up automatically with the next batch.
The endpoint silently drops records it can't parse or that are missing required fields, rather than rejecting the whole batch — so a misconfigured **Data sets** step shows up as healthy delivery on Akamai's side and empty cards on Searchable's side. Check these two things, in order:
**1. Log file format is Structured JSON.** Open **Data sets** and check **Log file format** near the top. It must be **Structured JSON**, not **JSON** — the two look nearly identical in the dropdown, but only Structured JSON emits one record per line, which is what our endpoint parses. This is the most common cause of a stream that delivers `204`s and produces nothing.
**2. Every required field is selected:**
* `reqID`, `reqMethod`, `reqHost`, `reqPath`, `UA`, `statusCode`, `cliIP`, `reqTimeSec`
Field names are case-sensitive — `UA` is capitalised and is not `reqUserAgent`. After missing `UA`, the most common single-field cause is missing `reqTimeSec`: without it the record is dropped outright.
If the format is right and all required fields are present, the next most common cause is a domain mismatch — see "Status stays on 'Waiting for first event'" below.
These two are not interchangeable, despite the similar names:
* **`reqTimeSec`** is the wall-clock timestamp of the request (epoch **seconds**). This is what Searchable uses to place the event in time, and it is **required** — a record without it is dropped.
* **`reqEndTimeMSec`** is a *duration* — how long the request took to process, in ms — **not** a wall-clock value despite the name. Searchable uses it for response time only.
Tick both. If you ticked only `reqEndTimeMSec`, no events reach your dashboard at all, because every record fails the required-field check.
Fix: open **Data sets**, tick `reqTimeSec`, and save. The stream re-activates in place and the next batch arrives correctly.
`reqID` is populated with a non-unique value, or `reqID` was omitted from the field selection altogether.
* Open the stream's **Data sets** step and confirm `reqID` (capital `ID`) is selected — Akamai's UI lists it alphabetically near the bottom of the request-section fields
* `reqID` is Akamai's per-request unique identifier and is auto-populated; no property-level VCL or PMUSER variables required
* If `reqID` is selected and you still see this symptom, contact support and include a few sample records — most often this turns out to be a property-level override blanking the value
Without `reqID`, Searchable falls back to a (timestamp, path, user-agent) heuristic that's much coarser. The fix is non-destructive — add `reqID` and republish.
The wall-clock field is `reqTimeSec` — epoch **seconds**, which Searchable converts to milliseconds on ingest. `reqEndTimeMSec` is a duration, not a timestamp, and is never used to place an event in time.
If timestamps look wrong, the usual cause is a property-level override rewriting `reqTimeSec`, or a stream config copied from a much older DataStream 1 export that maps a different field into that slot. Confirm `reqTimeSec` is ticked in **Data sets**, then contact support with a few sample records if it persists.
A few possible causes, in order of likelihood:
* The stream isn't activated — open the stream in Control Center and confirm the status badge reads **Active**, not **Inactive** or **Pending activation**. Activations on Production take 5–10 minutes
* Your domain in Searchable doesn't match the host the Akamai property serves (check **LLM Analytics → Setup → Confirm your domain**)
* The Akamai property fronts a different host than the one you're testing with — DataStream is scoped per-property, so traffic going through a different property won't appear
* No AI bot has visited yet — try visiting your site with a known AI user agent (e.g. `Mozilla/5.0 (compatible; GPTBot/1.0)`) to trigger a test event
If Akamai's **Monitor** tab shows successful `204` responses but Searchable still says no events, the issue is almost always a domain mismatch on the Searchable side.
Akamai's standard staging-network workflow works fine — activate the stream on **Staging** first, then point a few test requests at your staging hostname (Akamai exposes the staging network at `.edgesuite-staging.net` or via a `Pragma: akamai-x-cache-on` header trick from your origin). Successful staging delivery is a strong signal the production activation will work as well.
You'll see events arrive in the same Searchable project — there's no separate staging endpoint to worry about.
## Multi-site and region-level properties (domain mapping)
A single Akamai property sometimes serves traffic for many different hostnames — for example, a region-level property that fronts `example.co.uk`, `example.de`, and `example.fr`. With a standard integration token those requests would all land on one Searchable project. Domain mapping lets you route each hostname to the right Searchable project from a single DataStream stream, without touching the Akamai config or reissuing the token.
**Gated rollout.** The domain-mapping manager is available on request. If you don't see a **Domain
mappings** section on the Setup tab, reach out to support to have it enabled for your account.
### How it works
1. In Searchable, go to **LLM Analytics → Setup** and open **Domain mappings**.
2. Create a mapping and add host rules — one rule per hostname your Akamai property serves (e.g. `example.co.uk` → the UK project, `example.de` → the German project, and so on).
3. Generate a **domain-mapping token** from the same manager. The token looks the same as a standard `sa_…` integration token and goes in the same `X-Searchable-Token` header, raw and with no `Bearer ` prefix.
4. Paste the token into your DataStream's **Custom HTTP header** field (replacing any existing token).
Searchable inspects the `reqHost` field of each incoming log record and routes it to the matching project. **Hostnames that have no rule are silently discarded** — they are never stored. Rule changes propagate within about a minute; you don't need to touch the Akamai stream or generate a new token.
Any hostname your Akamai property serves that is **not** covered by a domain-mapping rule will be
dropped at ingestion and will not appear in any Searchable dashboard. Double-check your rules
cover every hostname you want tracked.
### Diagnostic events
DataStream diagnostic envelopes from a mapping token are not attributable to a single project and are dropped in the current release. If you need per-batch ingestion diagnostics, use a standard (single-project) integration token instead.
## Removing the integration
To stop sending traffic to Searchable:
1. Akamai → **CDN → DataStream → your stream → Deactivate** (and optionally delete the stream once it's deactivated)
2. Searchable → **LLM Analytics → Setup → Tokens** → revoke the token
Both sides are independent — revoking the token alone is enough to stop ingestion immediately, even if the stream stays configured in Akamai (its deliveries will start returning `401`, which Akamai will retry and then drop).
## Next steps
Open LLM Analytics to see which assistants are crawling your site.
Correlate AI crawls with search demand.
# Send Cloudflare traffic to Searchable (Logpush)
Source: https://docs.searchable.com/setup/cloudflare
Stream Cloudflare HTTP request logs directly to Searchable using a native Logpush job — Enterprise plan only
## What this does
[Cloudflare Logpush](https://developers.cloudflare.com/logs/about/) is Cloudflare's native, batched log delivery system. We point a Logpush job at Searchable's ingest endpoint, Cloudflare ships HTTP request logs to us, we classify the AI bots, and drop everything else.
**Logpush requires the Cloudflare Enterprise plan.** If you're on a different plan, use the **[Cloudflare Worker](/setup/cloudflare-worker)** path instead — it works on every plan including Free.
## Logpush vs. Worker — which one?
| | Logpush | Worker |
| ------------------------ | ------------------------- | --------------------------- |
| **Plan required** | Enterprise | Any plan, including Free |
| **Latency to dashboard** | \~30–60 seconds (batched) | Real-time (per-request) |
| **Setup complexity** | One Logpush job, no code | Paste a script, add a route |
| **Sites per zone** | All sites on the zone | Per-route |
If you're on Enterprise, Logpush is the lowest-overhead option. If you'd rather avoid an Enterprise feature dependency, the Worker path works on Enterprise too.
## Prerequisites
A Cloudflare zone on the Enterprise plan with Logpush enabled
Permission to create Logpush jobs on the zone
A Searchable project with your domain confirmed
## Setup (dashboard)
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Cloudflare Logpush** as your crawler source
4. Click **Generate token**
Searchable returns a single ready-to-paste destination URL with the auth header pre-encoded as a query parameter. It looks like this:
```
https://tracker.searchableanalytics.com/v1/cloudflare-logs?header_Authorization=Bearer%20sa_…
```
Copy it now — the token portion won't be shown again.
Cloudflare Logpush doesn't have a separate header field — auth has to be encoded into the destination URL itself using `header_*` query parameters. Searchable handles that encoding for you.
Open [dash.cloudflare.com](https://dash.cloudflare.com/) → your zone → **Analytics & Logs → Logpush**.
Click **Create a Logpush job**.
| Field | Value |
| -------------------- | ----------------------------------------------------------------------------- |
| **Dataset** | HTTP Requests |
| **Destination** | HTTP destination |
| **Destination URL** | the full URL you copied from Searchable (auth is already in the query string) |
| **Timestamp format** | Unix |
| **Fields** | see below |
Pick exactly these fields:
* `RayID`
* `ClientRequestMethod`
* `ClientRequestURI`
* `ClientRequestPath`
* `ClientRequestHost`
* `ClientRequestScheme`
* `ClientRequestUserAgent`
* `ClientRequestReferer`
* `ClientIP`
* `ClientCountry`
* `EdgeResponseStatus`
* `EdgeStartTimestamp`
* `OriginResponseTime`
* `EdgeColoCode`
* `CacheStatus`
* `EdgeResponseBytes`
The timestamp format **must be Unix**, not RFC3339. Logpush jobs default to RFC3339, and Searchable will reject batches that don't include a Unix timestamp.
Click **Save**. Cloudflare will validate the destination immediately — Searchable accepts the validation ping.
Return to **LLM Analytics → Setup** in Searchable. The status strip should show **Connected** within a few minutes once an AI bot hits your site.
## Setup (API)
If you'd rather create the job via the [Cloudflare API](https://developers.cloudflare.com/api/operations/logpush-jobs-create-logpush-job), here's the equivalent call. Replace `{zone_id}`, `{cf_api_token}`, and the `sa_…` placeholder with your own values.
```bash theme={null}
curl -X POST "https://api.cloudflare.com/client/v4/zones/{zone_id}/logpush/jobs" \
-H "Authorization: Bearer {cf_api_token}" \
-H "Content-Type: application/json" \
-d '{
"name": "searchable-ai-logs",
"logpull_options": "fields=RayID,ClientRequestMethod,ClientRequestURI,ClientRequestPath,ClientRequestHost,ClientRequestScheme,ClientRequestUserAgent,ClientRequestReferer,ClientIP,ClientCountry,EdgeResponseStatus,EdgeStartTimestamp,OriginResponseTime,EdgeColoCode,CacheStatus,EdgeResponseBytes×tamps=unix",
"destination_conf": "https://tracker.searchableanalytics.com/v1/cloudflare-logs?header_Authorization=Bearer%20sa_YOUR_INTEGRATION_TOKEN",
"dataset": "http_requests",
"enabled": true
}'
```
## Already have a token? Build the destination URL manually
If you have an existing `sa_…` token (saved from a previous Generate flow, stored in 1Password, etc.) you can construct the destination URL yourself:
```
https://tracker.searchableanalytics.com/v1/cloudflare-logs?header_Authorization=Bearer%20
```
Notes:
* The literal space between `Bearer` and the token must be percent-encoded as `%20`
* Our token alphabet (`sa_.`) is already URL-safe, so nothing else needs encoding
* Cloudflare's `header_*` query-parameter convention is documented [here](https://developers.cloudflare.com/logs/get-started/enable-destinations/http/)
You can also use the **"Already have a token? Build the URL"** form in Searchable's setup UI to do this for you.
## Verifying the connection
Cloudflare batches Logpush deliveries every \~30–60 seconds, so events take a moment to appear after the first AI bot hit.
In Searchable:
1. Go to **LLM Analytics → Setup**
2. Look at the status strip at the bottom of the page
3. Click **Check** if it still shows "Waiting for first event"
You can also confirm in Cloudflare: **Analytics & Logs → Logpush → your job**. The job's metrics show successful and failed delivery counts.
## Multiple zones
Each Logpush job is scoped to a single Cloudflare zone. If your domain is split across multiple zones (e.g. `example.com` and `example.io`):
1. Generate one integration token per zone, or reuse one — both work
2. Create one Logpush job per zone with the same destination URL
3. Searchable will tag events by host, so you'll still see them per-domain in the dashboard
## Troubleshooting
Open the job in Cloudflare and check the error message:
* **`401 Unauthorized`** — the `header_Authorization` query parameter is missing or malformed. Re-copy the destination URL from Searchable, or rebuild it manually using the format above.
* **`400 Bad Request`** — most often `timestamps=unix` is missing. Edit the job and confirm timestamp format is **Unix**.
* **`Invalid destination URL`** — Cloudflare's destination validation pings the endpoint. If validation fails, double-check the host (`tracker.searchableanalytics.com`) and that the URL has the `?header_Authorization=Bearer%20…` query string attached.
Logpush only delivers logs for traffic that's actually flowing through Cloudflare. Things to check:
* The Cloudflare zone is proxied (orange cloud) for the routes AI bots are hitting, not just DNS-only (grey cloud)
* The Logpush job is **enabled** (jobs can be paused)
* Your domain in Searchable matches the zone's hostname (check **LLM Analytics → Setup → Confirm your domain**)
If everything looks right, hit your site with a known AI user agent and wait \~60 seconds for the next Logpush batch:
```bash theme={null}
curl -H "User-Agent: GPTBot/1.0 (+https://openai.com/gptbot)" https://yourdomain.com/
```
If you also run the **[Cloudflare Worker](/setup/cloudflare-worker)** path on the same zone, both will send each AI-bot request. Searchable de-duplicates server-side using the Cloudflare Ray ID, so the dashboard shows each request once. If you'd rather not run both, pick one and disable the other.
No. Logpush is Enterprise-only on Cloudflare. Use the **[Cloudflare Worker](/setup/cloudflare-worker)** path instead — it works on Free, Pro, Business, and Enterprise.
## Removing the integration
1. Cloudflare → **Analytics & Logs → Logpush** → disable or delete the job
2. Searchable → **LLM Analytics → Setup → Tokens** → revoke the token
Both sides are independent — revoking the token alone is enough to stop ingestion immediately, even if the job stays configured (its deliveries will start returning `401`).
## Next steps
Edge Worker option — works on every Cloudflare plan.
Open LLM Analytics to see which assistants are crawling your site.
# Send Cloudflare traffic to Searchable (Worker)
Source: https://docs.searchable.com/setup/cloudflare-worker
Deploy a small Cloudflare Worker that forwards AI-bot requests to Searchable. Works on every Cloudflare plan, including Free.
## What this does
The Worker sits at Cloudflare's edge in front of your origin. For every inbound request it:
1. Lets the request flow through to your origin unchanged (no added latency for users)
2. Checks the user agent against Searchable's AI-bot registry
3. If it matches, fires a fire-and-forget POST to Searchable with the request metadata
The bot registry is fetched from Searchable and refreshed hourly, so new AI crawlers are picked up automatically — you never need to redeploy.
**Works on any Cloudflare plan, including Free.** Most sites stay well within the Workers free tier (100k requests/day). High-traffic sites can upgrade to Workers Paid for a few dollars a month.
## Prerequisites
A Cloudflare account with your domain on it (the domain doesn't have to be on a paid plan)
Permission to deploy Workers and add Worker routes to your zone
A Searchable project with your domain confirmed
## Setup
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Cloudflare Worker** as your crawler source
4. Click **Generate token**
Searchable templates the token directly into the Worker script in the next panel — no find-and-replace needed. Copy the whole script.
The Searchable UI is the easiest way to get the script — the token is auto-filled and you avoid typos. The reference script is below if you'd rather build it yourself.
Open [dash.cloudflare.com](https://dash.cloudflare.com/) → **Workers & Pages** → **Create**.
1. Pick the **Hello World** template
2. Name it (e.g. `searchable-tracker`)
3. Click **Deploy**
From the new Worker's overview page:
1. Click **Edit code**
2. Replace the entire file contents with the script you copied from Searchable
3. Click **Save and deploy**
A Worker by itself isn't on your domain — it has its own `*.workers.dev` URL. To make it observe your real traffic, add a route.
From the Worker's **Settings** tab:
1. Open **Domains & Routes** (older UIs label this **Triggers**)
2. Click **Add → Route**
3. Enter your route, e.g. `*yourdomain.com/*` (the leading `*` matches all subdomains)
4. Pick your zone and save
Return to **LLM Analytics → Setup** in your Searchable dashboard. The status strip should show **Connected** within a few minutes once an AI bot hits your site.
## Reference: Worker script
If you'd rather not copy the script from the Searchable UI, here's the reference. Replace `INTEGRATION_TOKEN` with the token you generated.
```js worker.js theme={null}
const SEARCHABLE_ENDPOINT = "https://tracker.searchableanalytics.com/v1/cloudflare-logs";
const SEARCHABLE_BOTS_URL = "https://tracker.searchableanalytics.com/v1/bots.json";
// Quick-start: paste your token here.
// Production: leave blank and set a Worker secret named INTEGRATION_TOKEN
// (Settings → Variables and Secrets). The secret wins if both are set.
const INTEGRATION_TOKEN = "sa_PASTE_YOUR_TOKEN_HERE";
let cachedPatterns = null;
let cachedAt = 0;
let loadPromise = null;
const PATTERNS_TTL_MS = 60 * 60 * 1000;
function ensurePatternsLoaded() {
if (loadPromise) return;
loadPromise = (async () => {
try {
const resp = await fetch(SEARCHABLE_BOTS_URL, { cf: { cacheTtl: 3600 } });
if (!resp.ok) return;
const artifact = await resp.json();
const patterns = (artifact.bots || [])
.filter((b) => b.user_agent_pattern)
.map((b) => {
try { return new RegExp(b.user_agent_pattern, "i"); }
catch { return null; }
})
.filter(Boolean);
if (patterns.length > 0) {
cachedPatterns = patterns;
cachedAt = Date.now();
}
} catch {}
loadPromise = null;
})();
}
const STATIC_ASSET_RE = /\.(css|js|mjs|map|woff2?|ttf|otf|eot|svg|png|jpe?g|gif|webp|avif|ico|mp3|mp4|webm|pdf)(\?|$)/i;
function shouldForward(ua) {
if (!cachedPatterns) return true;
if (!ua) return true;
return cachedPatterns.some((re) => re.test(ua));
}
async function forwardToSearchable(request, ua, token) {
try {
const url = new URL(request.url);
const cf = request.cf ?? {};
const entry = {
RayID: request.headers.get("cf-ray") ?? crypto.randomUUID(),
ClientRequestMethod: request.method,
ClientRequestURI: url.pathname,
ClientRequestPath: url.pathname,
ClientRequestHost: url.hostname,
ClientRequestScheme: url.protocol.replace(":", ""),
ClientRequestUserAgent: ua,
ClientRequestReferer: request.headers.get("referer") ?? "",
ClientIP: request.headers.get("cf-connecting-ip") ?? "0.0.0.0",
ClientCountry: cf.country ?? "",
EdgeResponseStatus: 0,
EdgeStartTimestamp: Date.now() * 1_000_000,
OriginResponseTime: 0,
EdgeColoCode: cf.colo ?? "",
CacheStatus: "",
EdgeResponseBytes: 0,
};
await fetch(SEARCHABLE_ENDPOINT, {
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/x-ndjson",
"X-Searchable-Source": "cloudflare-worker",
},
body: JSON.stringify(entry) + "\n",
});
} catch {}
}
export default {
async fetch(request, env, ctx) {
ctx.passThroughOnException();
if (STATIC_ASSET_RE.test(request.url)) return fetch(request);
if (!cachedPatterns || Date.now() - cachedAt > PATTERNS_TTL_MS) {
ensurePatternsLoaded();
}
const ua = request.headers.get("user-agent") ?? "";
const token = env.INTEGRATION_TOKEN || INTEGRATION_TOKEN;
if (token && shouldForward(ua)) {
ctx.waitUntil(forwardToSearchable(request, ua, token));
}
return fetch(request);
},
};
```
A few things worth knowing about this script:
* **It never blocks the response.** The forward to Searchable is `ctx.waitUntil(...)`, so even if Searchable is unreachable, your users see no slowdown.
* **It fails open.** While the bot registry is loading (cold start) the Worker forwards every request and lets Searchable's server-side classifier do the filtering. Once the registry loads, it filters at the edge to cut traffic.
* **Static assets are skipped.** CSS, JS, images, fonts, and video bypass the Worker entirely — those almost never come from AI crawlers, and there's no point burning a Worker invocation on each.
## Storing the token as a secret (recommended)
For tighter security, store the token as a Worker secret instead of leaving it inline.
1. In your Worker, open **Settings → Variables and Secrets**
2. Add a secret named `INTEGRATION_TOKEN` with your `sa_…` token as the value
3. In the script, blank the inline `INTEGRATION_TOKEN` constant: `const INTEGRATION_TOKEN = "";`
4. Redeploy
The Worker reads the secret if present and falls back to the constant otherwise. Same script, no other edits.
This means you can rotate the token in Cloudflare's UI without ever touching the Worker code.
## Cost
Each AI-bot request costs you one extra Worker invocation. The Workers Free plan includes 100,000 requests per day — that's about 3 million crawls per month, which covers nearly all sites. If you exceed it, the [Workers Paid plan](https://www.cloudflare.com/plans/developer-platform-pricing/) is \$5/month for 10 million requests.
The Worker itself does no CPU-intensive work (a regex check and a `fetch` call), so CPU time is negligible.
## Troubleshooting
Most likely the route isn't bound correctly.
* In Cloudflare, open the Worker → **Settings → Domains & Routes**
* Confirm the route pattern matches your live domain (e.g. `*yourdomain.com/*`, not `*yourdomain.dev/*`)
* Confirm the route's **Zone** is the zone that's actually serving traffic for the domain
If the route is right, hit your site with a curl using a known AI user agent:
```bash theme={null}
curl -H "User-Agent: GPTBot/1.0 (+https://openai.com/gptbot)" https://yourdomain.com/
```
Then click **Check** in Searchable. If that doesn't appear in the dashboard, the Worker's logs (Cloudflare → Worker → **Logs**) will show whether `forwardToSearchable` is running and whether Searchable returned a non-2xx status.
The token is missing or wrong.
* Confirm `INTEGRATION_TOKEN` (inline) or the secret named `INTEGRATION_TOKEN` is set to a `sa_…` value
* If you've recently revoked the token in Searchable, generate a new one and update the Worker
* The token must have **no quotes** around it in the secret value
You need permission to add Worker routes on the zone. If you don't have it:
* Ask the zone admin to add the route, or
* Use the **[custom REST API](/setup/custom)** path from your application server
If you also have **[Cloudflare Logpush](/setup/cloudflare)** sending traffic to Searchable, you'll get the same request from both sources. Searchable de-duplicates server-side using the Cloudflare Ray ID, so the dashboard shows each request once. If you'd rather not run both, pick one and disable the other.
## Removing the integration
1. Cloudflare → Worker → **Settings → Domains & Routes** → remove the route (the Worker stops observing traffic)
2. Optionally delete the Worker itself
3. Searchable → **LLM Analytics → Setup → Tokens** → revoke the token
## Next steps
On the Enterprise plan? See the native Logpush path.
Open LLM Analytics to see which assistants are crawling your site.
# Send Amazon CloudFront traffic to Searchable
Source: https://docs.searchable.com/setup/cloudfront
Stream CloudFront standard logs to Searchable through Amazon Data Firehose — works on any CloudFront distribution
## What this does
CloudFront's [Standard Logging V2](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/standard-logging.html) ships request logs to a destination of your choosing. We point a Kinesis Data Firehose stream at Searchable's ingest endpoint, Firehose batches log records to us, we classify the AI bots, and drop everything else.
**No code changes.** All configuration is done inside the AWS Console.
## Prerequisites
A CloudFront distribution (works on any plan — Standard Logging V2 is a free CloudFront feature)
Permission to create Firehose delivery streams and edit the CloudFront distribution
A Searchable project with your domain confirmed
You only pay for the Firehose ingestion + delivery (typically a few cents per GB of AI-bot traffic). There is no CloudFront charge for enabling Standard Logging V2.
## Setup
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Amazon CloudFront** as your crawler source
4. Click **Generate token**
Copy the token now — it starts with `sa_…` and won't be shown again. You can always generate a new one if you lose it.
The endpoint URL is fixed:
```
https://tracker.searchableanalytics.com/v1/cloudfront-logs
```
Sanity check before pointing Firehose at the endpoint: `curl https://tracker.searchableanalytics.com/v1/cloudfront-logs` should return `200 OK`. If you don't see that, your network can't reach the endpoint and Firehose will silently buffer to the S3 backup bucket instead.
Open the [CloudFront console](https://console.aws.amazon.com/cloudfront/v4/home) → your distribution → **Logging**.
Click **Add standard log destination**.
| Field | Value |
| -------------------- | -------------------- |
| **Destination type** | Amazon Data Firehose |
| **Output format** | JSON |
Then click **Create new Firehose stream** — this opens the Firehose wizard in a new tab.
In the Firehose wizard:
| Field | Value |
| --------------------- | ------------------------------------------------------------ |
| **Source** | Direct PUT |
| **Destination** | HTTP Endpoint |
| **HTTP endpoint URL** | `https://tracker.searchableanalytics.com/v1/cloudfront-logs` |
| **Access key** | paste the `sa_…` token from Searchable |
| **Content encoding** | GZIP |
| **Buffer hints** | **1 MiB** / **60s** |
Buffer hints matter. The Firehose default is 5 MiB, which sits right at Searchable's 5 MB compressed-batch cap — high-traffic distributions can intermittently hit `413 Payload Too Large`. Set the size hint to **1 MiB** and the interval to **60 seconds**.
Firehose can't set arbitrary request headers, so it sends the **Access key** value as the `X-Amz-Firehose-Access-Key` header instead. Searchable's endpoint accepts either that or `Authorization: Bearer sa_…`, so the same token works for Firehose, a custom Lambda relay, or a curl test.
Firehose requires an S3 backup bucket for records it can't deliver.
| Field | Value |
| -------------------- | ---------------------- |
| **S3 backup bucket** | any bucket you control |
| **Backup mode** | **Failed data only** |
"Failed data only" means you only pay to store records the endpoint actually rejects (for example, after a token revocation). Don't pick "All data" — it would duplicate every CloudFront log into S3 unnecessarily.
Finish creating the Firehose stream.
Return to the CloudFront tab and select the Firehose stream you just created.
Pick these standard log fields:
**Required** (the endpoint drops records missing any of these):
* `timestamp`
* `sc-status`
* `cs-method`
* `cs-uri-stem`
* `x-host-header`
* `cs-user-agent`
**Recommended** (improves enrichment + debugging; anything you select beyond the required set is preserved as `custom_properties` in Searchable):
* `c-ip`
* `c-country`
* `cs-protocol`
* `cs-uri-query`
* `cs-referer`
* `sc-bytes`
* `time-taken`
* `x-edge-request-id`
* `x-edge-location`
* `x-edge-result-type`
Save the log destination.
Firehose batches every \~60 seconds, so events take a moment to appear after the first AI bot hit.
Return to **LLM Analytics → Setup** in Searchable. The Amazon CloudFront card should show **Connected** within a few minutes once an AI bot hits your site.
## Verifying the connection
In Searchable:
1. Go to **LLM Analytics → Setup**
2. Look at the Amazon CloudFront card status
3. Click **Check** if it still shows "Waiting for first event"
| Status | What it means |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Waiting for first event** | The Firehose stream is configured but no AI bot has hit your site yet. Typical wait is a few hours for sites that are already indexed. |
| **Connected** | Events are arriving. The card shows the count from the last 24 hours. |
You can also confirm in AWS: **Amazon Data Firehose → your stream → Monitoring**. The stream's metrics show incoming records (from CloudFront) and successful HTTP deliveries (to Searchable). The S3 backup bucket should stay near-empty when "Failed data only" is set.
## What Searchable receives
For each request that matches an AI-bot user agent, Searchable receives:
* HTTP method, path, and host (query strings stripped before storage)
* User agent
* Referer
* Country code (from `c-country`)
* Response status, response bytes
* Edge timing (`time-taken`)
* CloudFront edge metadata (`x-edge-request-id`, `x-edge-location`, `x-edge-result-type`) — preserved as `custom_properties` for debugging
Bodies, headers other than `User-Agent` / `Referer`, cookies, and full IPs are never sent or stored. The CloudFront edge request ID is also used to de-duplicate Firehose redeliveries server-side.
## Multiple distributions
Each Firehose stream is bound to a single CloudFront distribution's log destination. If your domain spans multiple distributions (for example, separate distributions for `example.com` and `assets.example.com`):
1. Generate one integration token, or reuse one across distributions — both work
2. Create one Firehose stream per distribution, all pointing at the same HTTP endpoint
3. Searchable tags events by host, so you'll still see them split by domain in the dashboard
## Troubleshooting
Open the Firehose stream in the AWS Console → **Monitoring → Destination error logs** for the specific error. The common ones:
* **`401 Unauthorized`** — the `sa_…` token in the **Access key** field is missing, wrong, or has been revoked in Searchable. Re-paste the token, or generate a new one from **LLM Analytics → Setup**.
* **`413 Payload Too Large`** — the Firehose buffer hint is too big. Drop the size hint to **1 MiB** and the interval to **60 seconds**, then save. Firehose will retry the buffered batches once they shrink.
* **`400 Bad Request`** — the CloudFront log output format isn't JSON, or the required fields aren't selected. Edit the CloudFront log destination, set **Output format** to **JSON**, and confirm `timestamp`, `sc-status`, `cs-method`, `cs-uri-stem`, `x-host-header`, and `cs-user-agent` are all checked.
While errors are climbing, Firehose buffers the affected records into your S3 backup bucket — fix the root cause and the stream catches back up automatically.
CloudFront only delivers logs for traffic that's actually being served by the distribution. Things to check:
* The CloudFront distribution is **Enabled** (not disabled or paused)
* The Firehose stream is **Active** (not in `CREATING` or `DELETING` state)
* Your domain in Searchable matches the alternate domain (CNAME) on the distribution (check **LLM Analytics → Setup → Confirm your domain**)
* The log destination is attached to the distribution — easy to miss if the Firehose-creation wizard was opened separately and you forgot to come back to CloudFront's Logging tab
If everything looks right, hit your site with a known AI user agent and wait \~60 seconds for the next Firehose batch:
```bash theme={null}
curl -H "User-Agent: GPTBot/1.0 (+https://openai.com/gptbot)" https://yourdomain.com/
```
The "Failed data only" backup bucket only fills up when the HTTP endpoint rejects records — typically a token / config issue. Inspect a recent failed object in the bucket:
* It contains the original CloudFront records along with an error message from the endpoint (`401`, `413`, `400`, etc.)
* Use the message to identify the root cause (see the `Firehose 'Destination error count' is climbing` section above)
* Once you fix the config, new records flow through to Searchable; the records already in the backup bucket aren't automatically re-delivered (Firehose treats the backup as terminal storage)
Firehose is at-least-once, so it can occasionally redeliver a batch after a transient network error. Searchable de-duplicates on `x-edge-request-id` server-side, so duplicate events don't appear in the dashboard — provided you selected `x-edge-request-id` in the CloudFront log fields. If you skipped it, dedup falls back to a (timestamp, path, user-agent) heuristic that's less precise. Edit the log destination, add `x-edge-request-id`, and save.
The same endpoint accepts plain NDJSON POSTs (no Firehose envelope), so you can post log records directly from a Lambda or any custom collector. Use:
* `POST https://tracker.searchableanalytics.com/v1/cloudfront-logs`
* `Authorization: Bearer sa_…` header
* `Content-Type: application/x-ndjson` (gzip optional — set `Content-Encoding: gzip` if you compress)
* One CloudFront log record per line, using the same field names as Standard Logging V2 (`cs-method`, `cs-uri-stem`, `x-host-header`, `cs-user-agent`, `sc-status`, `timestamp`, etc.)
The endpoint replies with `204 No Content` on success.
## Removing the integration
1. AWS Console → **CloudFront → your distribution → Logging** → delete the standard log destination
2. AWS Console → **Amazon Data Firehose → your stream** → delete the stream (and the S3 backup bucket if you no longer need it)
3. Searchable → **LLM Analytics → Setup → Tokens** → revoke the token
Both sides are independent — revoking the token alone is enough to stop ingestion immediately, even if the Firehose stream stays configured (its deliveries will start returning `401` and land in the backup bucket).
## Next steps
Open LLM Analytics to see which assistants are crawling your site.
Correlate AI crawls with search demand.
# Custom integration
Source: https://docs.searchable.com/setup/custom
Ship AI-bot traffic to Searchable from any stack — Next.js, Express, Fastify, Go, Python, Ruby, anything that can make an HTTP call — using middleware or the REST API.
## What this is
When your hosting platform doesn't have a first-class connector (or you just want full control), Searchable accepts events directly from your application via two paths:
Drop-in Node.js package — `@searchablehq/middleware`. Wraps Next.js middleware with one line. The primitives also compose into Express, Fastify, or anything else on Node.
Direct HTTP POST to Searchable's ingest endpoint. Use from any language — Go, Python, Ruby, PHP, a shell script, or a CDN worker we don't yet support natively.
Both paths land in the same place. They share the same auth model (workspace API key + project site token) and feed the same dashboards.
**No data is mocked.** Events you POST flow through the same pipeline as our native Vercel, Cloudflare, and Netlify connectors, and the same server-side bot classifier filters non-AI user agents.
## Which one should I use?
Use the **[middleware SDK](/setup/middleware)**. One import, one config object, done. It plugs into `middleware.ts` and captures every non-static request automatically.
Use the **[middleware SDK's primitives](/setup/middleware#express-fastify-other-node-frameworks)**. The package exports `buildEventPayload` and `sendEvent` so you can wire it into any Node framework — typically as a request-completion hook or `res.on("finish")` listener.
Use the **[REST API](/setup/rest-api)**. It's a single `POST /v1/events` call with `Authorization: Bearer sk_live_…` and a JSON body — language-agnostic, no SDK needed.
Start with a `curl` against the **[REST API](/setup/rest-api)** using a fake AI user agent (e.g. `GPTBot/1.0`). The status strip in **LLM Analytics → Setup** flips to **Connected** within a few seconds. Once that's green, switch to the middleware SDK or your real integration.
Use the **[REST API](/setup/rest-api)** from your worker. Cloudflare's native `/v1/cloudflare-logs` endpoint is the same shape — if you're forwarding NDJSON request logs from a Cloudflare-like worker, point them at `/v1/cloudflare-logs` instead and reuse the [Cloudflare Worker setup](/setup/cloudflare-worker).
## Common prerequisites
Both paths need the same two credentials.
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup → Confirm your domain**
3. The private **Site token** for this project starts with `st_…` — copy it
The site token identifies which project events belong to. It's tied to the project's primary domain.
Searchable also issues a **public** site token (`pst_…`) for the browser beacon. That one is *not* the right one for server-side integrations — use the private `st_…` token here.
1. In the same Setup page, click **Custom** as your crawler source
2. Open the connector dialog → **Generate API key**
3. Searchable creates a key with the `log_events` permission, scoped to the current project, and shows it once — copy it now
Keys start with `sk_live_…`. They're signed JWT-style tokens — the worker verifies them at Cloudflare's edge with no DB round-trip, so they don't add per-request latency.
The API key is only shown once. If you lose it, revoke and regenerate from **Settings → API Keys** or the Custom connector dialog.
## What ends up in Searchable
For each event you send, Searchable records:
* HTTP method, path, host (query strings are stripped before storage)
* Status code, response time, response bytes
* User agent (used to classify the AI bot)
* Referer and referrer domain
* UTM parameters
* Geo country (from the inbound IP, if available)
* Timestamp
Cookies, request/response bodies, and full IP addresses are never stored. The middleware SDK anonymizes IPs by default (zeroes the last octet) before sending.
The server-side classifier drops any user agent that isn't a known AI crawler — so even if you POST every request from your app, the dashboard only shows GPTBot, ClaudeBot, PerplexityBot, and the rest of the AI-bot universe.
## How auth flows
```
Your app ──POST──→ tracker.searchableanalytics.com
│
│ Authorization: Bearer sk_live_…
│ Body: { site_token: "st_…", events: [...] }
▼
Verify HMAC signature on sk_live_… at the edge
(no DB lookup — fast fail on 401 / 403)
│
▼
Resolve site_token → workspace + domain
│
▼
Forward to ingest → ClickHouse
```
`sk_live_*` carries `{ workspace_id, key_id }` in its signed payload. The worker verifies the HMAC at Cloudflare's edge and tags every forwarded event with both values, so revoking a key in the dashboard immediately stops any in-flight POSTs that use it.
## Pick a path
Step-by-step for Next.js + a recipe for Express/Fastify.
Endpoint, headers, payload schema, and a `curl` you can run today.
## Next steps
Open LLM Analytics to see which assistants are crawling your site.
Layer in keyword data so you can correlate AI crawls with search demand.
# Send Fastly traffic to Searchable (Real-Time Log Streaming)
Source: https://docs.searchable.com/setup/fastly-logs
Configure a Fastly HTTPS Logging endpoint to stream request logs to Searchable. No code changes — all configuration is done inside the Fastly UI.
## What this does
Fastly's Real-Time Log Streaming ships request log records to a destination of your choosing in near-real-time. We point that stream at Searchable's tracker endpoint, classify the AI bots, and drop everything else. No code changes — all configuration happens inside your Fastly service.
**No code changes.** All configuration is done inside the Fastly UI.
## Prerequisites
A Fastly account on any paid plan (HTTPS Logging is available on all paid plans)
Admin or Engineer-level access to the Fastly service you want to instrument
A Searchable project with your domain confirmed
## Setup
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Fastly** as your crawler source
4. Click **Generate token**
Copy the token now — it starts with `sa_…` and won't be shown again. You can always generate a new one if you lose it.
In the Fastly UI, navigate to your service:
**Service → Logging → HTTPS → Create endpoint**
This creates a new draft version of your service config; you'll activate it at the end.
Fill in these fields:
| Field | Value |
| ----------------------- | -------------------------------------------------------- |
| **Name** | `Searchable LLM Analytics` (or any label you prefer) |
| **URL** | `https://tracker.searchableanalytics.com/v1/fastly-logs` |
| **Method** | `POST` |
| **Content type** | `application/json` |
| **Log format version** | `2` |
| **Custom header name** | `Authorization` |
| **Custom header value** | `Bearer ` |
| **Log format** | (paste the template below) |
The custom header value must be `Bearer ` followed by the full `sa_…` token, with one space and no quotes. The header name must be exactly `Authorization`.
Paste this into the **Log format** field exactly as-is. Do **not** edit any of the `%{...}` substitutions — they are Fastly VCL/log-format directives that we depend on for correct request attribution and deduplication:
```json theme={null}
{
"timestamp": "%{begin:%Y-%m-%dT%H:%M:%SZ}t",
"client_ip": "%{req.http.Fastly-Client-IP}V",
"method": "%{req.method}V",
"url": "%{req.url}V",
"host": "%{req.http.host}V",
"status": %{resp.status}V,
"response_time": %{time.elapsed.msec}V,
"user_agent": "%{json.escape(req.http.User-Agent)}V",
"referer": "%{json.escape(req.http.Referer)}V",
"fastly_request_id": "%{req.xid}V",
"country": "%{client.geo.country_code}V",
"region": "%{client.geo.region}V",
"city": "%{json.escape(client.geo.city)}V"
}
```
`fastly_request_id` must use `%{req.xid}V` — Fastly's canonical per-request unique identifier. Substituting any other token (e.g. `Fastly-SOA-ID` or a custom `X-Request-ID`) will silently break deduplication on our side and events will appear to be lost.
Click **Create** to save the endpoint, then **Activate** the new service version. Fastly batches log records and ships them within a few seconds; expect events to appear in Searchable within a couple of minutes once an AI bot hits your site.
## Verifying the connection
In Searchable:
1. Go to **LLM Analytics → Setup**
2. Look at the Fastly card status
3. Click **Check** if it still shows "Waiting for first event"
| Status | What it means |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **Waiting for first event** | The endpoint is configured but no AI bot has hit your site yet. Typical wait is a few hours for sites that are already indexed. |
| **Connected** | Events are arriving. The card shows the count from the last 24 hours. |
## Geo enrichment
`country`, `region`, and `city` arrive from Fastly's edge geo lookups (`client.geo.*`). If geo lookups aren't enabled on your service (the default is on for paid plans), those fields will arrive empty — everything else still works, and the integration counts as healthy. You can enable geo at **Service → Settings → Geolocation**.
## Troubleshooting
The Authorization header is missing or wrong.
* Make sure you added a **custom header** named exactly `Authorization`
* The value must be `Bearer ` followed by the full `sa_…` token, with one space and no quotes
* If you've recently revoked the token in Searchable, generate a new one and update the endpoint
The log format is likely wrong.
* Confirm **Log format version** is set to **2**, not 1 — version 1 wraps each record in a different shape that our endpoint doesn't accept
* Confirm the log format template was pasted exactly, including all `%{...}` substitutions. Do not remove any directive, even if it looks redundant
* Confirm the **Content type** is `application/json`
`fastly_request_id` is being populated with a non-unique value.
* Confirm the template uses `%{req.xid}V` (not `%{req.http.Fastly-SOA-ID}V` or any other header)
* `req.xid` is auto-populated by Fastly on every request and requires no special VCL setup — if it's empty in your logs, contact Fastly support
A few possible causes:
* The new service version was never activated — go to **Service → Versions** and confirm the version containing the HTTPS endpoint is currently **Active**
* Your domain in Searchable doesn't match the site served by Fastly (check **LLM Analytics → Setup → Confirm your domain**)
* The endpoint is configured but no AI bot has visited yet — try visiting your site with a known AI user agent (e.g. `Mozilla/5.0 (compatible; GPTBot/1.0)`) to trigger a test event
If deliveries are succeeding in Fastly's logs view but nothing appears in Searchable, that points to a domain mismatch or an Authorization-header issue.
## Removing the integration
To stop sending traffic to Searchable:
1. Fastly → **Service → Logging → HTTPS** → delete the endpoint and activate a new service version
2. Searchable → **LLM Analytics → Setup → Tokens** → revoke the token
Both sides are independent — revoking the token alone is enough to stop ingestion immediately, even if the endpoint stays configured in Fastly (its deliveries will start returning `401`).
## Next steps
Open LLM Analytics to see which assistants are crawling your site.
Correlate AI crawls with search demand.
# Send Google Cloud traffic to Searchable
Source: https://docs.searchable.com/setup/gcp-logs
Forward GCP HTTPS Load Balancer and Cloud CDN logs to Searchable via a Pub/Sub push subscription routed through a small Cloud Run relay.
## What this does
Google Cloud Logging captures every request that hits your HTTPS Load Balancer or Cloud CDN. You'll route those logs to a Pub/Sub topic, push them through a small Cloud Run relay inside your project, and forward them to Searchable. We classify AI bots at our edge and drop everything else.
Everything runs inside your GCP project. The relay is stateless, idempotent, and only forwards payloads — it doesn't read or store them.
## Prerequisites
A GCP project running an HTTPS Load Balancer or Cloud CDN
`roles/pubsub.admin`, `roles/logging.admin`, and `roles/run.admin` on that project (or equivalent)
`gcloud` CLI installed and authenticated, or access to Cloud Shell
A Searchable project with your domain confirmed
## Setup
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Google Cloud Platform** as your crawler source
4. Click **Generate token**
Copy the token now — it starts with `sa_…` and won't be shown again. You can always generate a new one if you lose it.
In Cloud Shell (or any terminal with `gcloud` authenticated to the target project):
```bash theme={null}
gcloud pubsub topics create searchable-ai-traffic
```
This is a dedicated topic that will hold log entries en route to Searchable. Keeping it separate from any other logging pipeline you have makes troubleshooting and removal trivial.
Create an empty directory and add two files. The relay is a single HTTP handler that adds the `X-Searchable-Token` header and forwards the Pub/Sub push body to Searchable unchanged.
`package.json`:
```json theme={null}
{
"name": "searchable-relay",
"type": "module",
"main": "index.js",
"scripts": { "start": "node index.js" },
"dependencies": {
"hono": "^4.0.0",
"@hono/node-server": "^1.0.0"
}
}
```
`index.js`:
```js theme={null}
import { Hono } from "hono";
import { serve } from "@hono/node-server";
const app = new Hono();
app.get("/", (c) => c.text("ok", 200));
app.post("/", async (c) => {
const body = await c.req.text();
const upstream = await fetch(process.env.SEARCHABLE_ENDPOINT, {
method: "POST",
headers: {
"content-type": "application/json",
"X-Searchable-Token": process.env.SEARCHABLE_TOKEN,
},
body,
});
return c.body(null, upstream.status);
});
serve({ fetch: app.fetch, port: parseInt(process.env.PORT ?? "8080", 10) });
```
Create a dedicated service account for Pub/Sub to invoke the relay as, deploy with `--no-allow-unauthenticated`, then grant it `roles/run.invoker`. Replace `` with the token from step 1:
```bash theme={null}
gcloud iam service-accounts create searchable-pubsub-invoker \
--display-name="Searchable Pub/Sub invoker"
gcloud run deploy searchable-relay \
--source=. \
--region=us-central1 \
--no-allow-unauthenticated \
--set-env-vars=SEARCHABLE_ENDPOINT=https://tracker.searchableanalytics.com/v1/gcp-logs,SEARCHABLE_TOKEN=
gcloud run services add-iam-policy-binding searchable-relay \
--region=us-central1 \
--member=serviceAccount:searchable-pubsub-invoker@$(gcloud config get-value project).iam.gserviceaccount.com \
--role=roles/run.invoker
```
Cloud Run will reject any invocation that isn't signed by `searchable-pubsub-invoker`, so the relay can't be called by anyone who happens to find the URL.
For production, store the token in Secret Manager instead of passing it via `--set-env-vars` (which leaves the cleartext value in `gcloud run services describe` output and your shell history). Create a secret, grant the Cloud Run runtime service account `roles/secretmanager.secretAccessor`, then swap `--set-env-vars=SEARCHABLE_TOKEN=...` for `--set-secrets=SEARCHABLE_TOKEN=projects//secrets/searchable-token:latest`.
Copy the **Service URL** printed by `gcloud run deploy` — you'll use it in the next step.
Replace `` with the Service URL from the previous step. The subscription mints an OIDC token from `searchable-pubsub-invoker` for every push:
```bash theme={null}
gcloud pubsub subscriptions create searchable-ai-traffic-sub \
--topic=searchable-ai-traffic \
--push-endpoint= \
--push-auth-service-account=searchable-pubsub-invoker@$(gcloud config get-value project).iam.gserviceaccount.com \
--ack-deadline=30 \
--min-retry-delay=10s \
--max-retry-delay=600s
```
The Searchable integration token is injected by the relay; the OIDC service-account auth here is what gates access to the relay itself.
Route HTTPS Load Balancer and Cloud CDN logs into the topic:
```bash theme={null}
gcloud logging sinks create searchable-ai-traffic-sink \
pubsub.googleapis.com/projects/$(gcloud config get-value project)/topics/searchable-ai-traffic \
--log-filter='resource.type="http_load_balancer" OR resource.type="cloud_cdn"'
```
GCP prints a service-account email after this command — grant it `roles/pubsub.publisher` on your project. The exact `gcloud` command is shown in the output; alternatively in the Console you'll see a yellow banner asking you to authorize the sink.
## Verifying the connection
In Searchable:
1. Go to **LLM Analytics → Setup**
2. Look at the Google Cloud Platform card status
3. Click **Check** if it still shows "Waiting for first event"
| Status | What it means |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| **Waiting for first event** | The subscription is configured but no AI bot has hit your site yet. Typical wait is a few hours for sites that are already indexed. |
| **Connected** | Events are arriving. The card shows the count from the last 24 hours. |
## Geo enrichment caveat
GCP HTTPS Load Balancer logs do **not** include geographic enrichment by default — `country`, `region`, and `city` will arrive empty in Searchable. The integration is otherwise fully functional. If you need geo, the simplest workaround is to also instrument your site with the Searchable Beacon (`s.js`), which derives geo from the visitor's request.
## Troubleshooting
The relay isn't sending the `X-Searchable-Token` header — either it's misconfigured or the token has been revoked.
* Confirm the Cloud Run service has `SEARCHABLE_TOKEN` set. List env var **names** only (not values) with `gcloud run services describe searchable-relay --region=us-central1 --format='value(spec.template.spec.containers[0].env[].name)'`. If you used Secret Manager, the entry shows as `SEARCHABLE_TOKEN` and the value lives in the secret
* If you've recently revoked the token in Searchable, generate a new one and redeploy the relay with the new value
Pub/Sub can't reach the relay, or the log filter is sending non-HTTP logs.
* Verify the subscription's push endpoint in the Console (Pub/Sub → Subscriptions → searchable-ai-traffic-sub → Edit) matches the deployed Cloud Run URL
* Check Cloud Run logs (`gcloud run services logs read searchable-relay --region=us-central1 --limit=50`) for non-200 responses — those become Pub/Sub retries
* Verify the sink filter is exactly `resource.type="http_load_balancer" OR resource.type="cloud_cdn"`. Broader filters can send non-HTTP logs that we reject with 204 (no retry) but also waste your Pub/Sub quota
GCP requires the sink's service account to have `roles/pubsub.publisher` on the topic. Without it the sink silently drops messages.
* Run `gcloud logging sinks describe searchable-ai-traffic-sink` to find the writer service account
* Grant it publisher on the topic: `gcloud pubsub topics add-iam-policy-binding searchable-ai-traffic --member=serviceAccount: --role=roles/pubsub.publisher`
Some GCP orgs enforce policies that further restrict Cloud Run. The default setup already deploys with `--no-allow-unauthenticated`, which satisfies most org policies — these errors usually point at one of the others:
* `constraints/run.allowedIngress` forces internal-only: redeploy with `--ingress=internal-and-cloud-load-balancing` and place a Pub/Sub-VPC connector in front, or run the relay on Cloud Functions instead
* `constraints/iam.disableServiceAccountCreation` blocks the `gcloud iam service-accounts create` command: use an existing service account your org already trusts and reuse its email in both `add-iam-policy-binding` and `--push-auth-service-account`
* `constraints/iam.allowedPolicyMemberDomains` blocks the invoker binding: have an admin add the project's service-agent domain to the allow-list, then re-run the binding command
A few possible causes:
* The Log Sink filter doesn't match your service — confirm your HTTPS Load Balancer logs actually populate Cloud Logging (View → Logs Explorer → filter on `resource.type="http_load_balancer"` and confirm you see entries)
* Your domain in Searchable doesn't match the site served by GCP (check **LLM Analytics → Setup → Confirm your domain**)
* No AI bot has visited yet — try visiting your site with a known AI user agent (e.g. `Mozilla/5.0 (compatible; GPTBot/1.0)`) to trigger a test event
If Pub/Sub's "Push attempt" metrics show successful 204 responses but Searchable still says no events, that points to a domain mismatch.
## Removing the integration
To stop sending traffic to Searchable and tear down the GCP-side resources:
```bash theme={null}
gcloud logging sinks delete searchable-ai-traffic-sink
gcloud pubsub subscriptions delete searchable-ai-traffic-sub
gcloud pubsub topics delete searchable-ai-traffic
gcloud run services delete searchable-relay --region=us-central1
gcloud iam service-accounts delete \
searchable-pubsub-invoker@$(gcloud config get-value project).iam.gserviceaccount.com
```
Then go to Searchable → **LLM Analytics → Setup → Tokens** and revoke the integration token.
Both sides are independent — revoking the token alone is enough to stop ingestion immediately, even if the GCP-side resources stay configured (push deliveries will start returning `401`, which Pub/Sub will retry until the messages expire).
## Next steps
Open LLM Analytics to see which assistants are crawling your site.
Correlate AI crawls with search demand.
# Send traffic to Searchable with the Middleware SDK
Source: https://docs.searchable.com/setup/middleware
Use @searchablehq/middleware to capture AI-bot traffic from any Node app. First-class support for Next.js, and primitives for Express, Fastify, and other Node frameworks.
## What this is
`@searchablehq/middleware` is a small Node package that captures inbound requests in your application and fires a non-blocking POST to Searchable's ingest endpoint. The Searchable backend then runs the same AI-bot classifier the rest of our connectors use, so only GPTBot, ClaudeBot, PerplexityBot, and other AI agents end up in your dashboard.
**Zero added latency.** The SDK fires events fire-and-forget after your response is built — your users never wait on Searchable. If the network is down or Searchable is unreachable, the request still completes.
The package ships with a first-class `withSearchable` wrapper for Next.js middleware. The same core primitives (`buildEventPayload`, `sendEvent`) can be reused to wire any other Node framework — examples for Express and Fastify are below.
## Prerequisites
A Node 18+ application (Next.js 13+, Express, Fastify, etc.)
A Searchable project with your domain confirmed
The two credentials from the [common prerequisites](/setup/custom#common-prerequisites): a project **site token** (`st_…`) and a workspace **API key** (`sk_live_…`)
## Install
```bash theme={null}
# pnpm
pnpm add @searchablehq/middleware
# npm
npm install @searchablehq/middleware
# yarn
yarn add @searchablehq/middleware
```
The package has no required runtime dependencies. `next` is an optional peer dependency — only loaded when you import from `@searchablehq/middleware/nextjs`.
## Next.js setup
In `.env.local` (or your hosting platform's env-var settings):
```bash .env.local theme={null}
SEARCHABLE_SITE_TOKEN=st_your_token_here
SEARCHABLE_API_KEY=sk_live_your_key_here
```
Both values come from **LLM Analytics → Setup → Custom** in your Searchable dashboard.
In your Next.js project root:
```ts middleware.ts theme={null}
import { withSearchable } from "@searchablehq/middleware/nextjs";
export default withSearchable({
siteToken: process.env.SEARCHABLE_SITE_TOKEN!,
apiKey: process.env.SEARCHABLE_API_KEY!,
});
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};
```
The `matcher` keeps the middleware off Next's static asset routes — those almost never come from AI crawlers, and there's no point burning a middleware invocation on each.
Pass your existing middleware as the second argument to `withSearchable`. Searchable runs first, then yields to your logic:
```ts middleware.ts theme={null}
import { withSearchable } from "@searchablehq/middleware/nextjs";
import { NextResponse } from "next/server";
export default withSearchable(
{
siteToken: process.env.SEARCHABLE_SITE_TOKEN!,
apiKey: process.env.SEARCHABLE_API_KEY!,
},
async (request) => {
// Your existing middleware logic here.
return NextResponse.next();
},
);
```
Ship the change to your hosting platform. The middleware runs on every non-static request and starts forwarding events immediately.
Open **LLM Analytics → Setup** in Searchable — the status strip flips to **Connected** within a few minutes of the next AI crawler hitting your site.
## Config reference
```ts theme={null}
interface SearchableConfig {
/** Site token (st_*). Required. */
siteToken: string;
/** Workspace API key (sk_live_*). Required — sent as `Authorization: Bearer …`. */
apiKey: string;
/** Collector endpoint URL. Default: Searchable's tracker worker. */
endpoint?: string;
/** Zero the last IP octet before sending. Default: true. */
anonymizeIp?: boolean;
/** Log every captured event to stdout. Default: false. */
debug?: boolean;
/** Skip capture for matching paths. Return true to skip. */
ignore?: (path: string) => boolean;
/** Inject custom properties into the event. */
custom?: (request: Request) => Record;
}
```
### Skipping paths
By default, the SDK auto-skips `/_next/*` and common static-asset extensions (`.js`, `.css`, `.png`, `.jpg`, `.svg`, `.ico`, `.woff`, `.woff2`, `.ttf`, `.map`).
Add custom skips for health checks, internal APIs, or anything else you don't want to count:
```ts theme={null}
withSearchable({
siteToken: process.env.SEARCHABLE_SITE_TOKEN!,
apiKey: process.env.SEARCHABLE_API_KEY!,
ignore: (path) =>
path.startsWith("/api/health") || path.startsWith("/api/internal"),
});
```
### Custom properties
Anything you return from `custom(request)` is attached to the event under `parameters` and is queryable from the dashboard:
```ts theme={null}
withSearchable({
siteToken: process.env.SEARCHABLE_SITE_TOKEN!,
apiKey: process.env.SEARCHABLE_API_KEY!,
custom: (request) => ({
tenant: request.headers.get("x-tenant-id") ?? "unknown",
abVariant: request.headers.get("x-experiment-bucket") ?? "control",
}),
});
```
### Debug mode
In development, set `debug: true` to log every captured event to your terminal:
```ts theme={null}
withSearchable({
siteToken: process.env.SEARCHABLE_SITE_TOKEN!,
apiKey: process.env.SEARCHABLE_API_KEY!,
debug: process.env.NODE_ENV === "development",
});
```
You'll see lines like:
```
[searchable/middleware] GET /pricing → 200 (45ms)
```
Turn it off in production — every event would also write to stdout.
## Express, Fastify, other Node frameworks
The Next.js helper is a thin convenience wrapper around two exported primitives:
```ts theme={null}
import {
buildEventPayload,
sendEvent,
type CapturedRequest,
} from "@searchablehq/middleware";
```
Wire them into any framework with an after-response hook.
### Express
```ts server.ts theme={null}
import express from "express";
import {
buildEventPayload,
sendEvent,
anonymizeIp,
} from "@searchablehq/middleware";
const app = express();
app.use((req, res, next) => {
const start = Date.now();
res.on("finish", () => {
const captured = {
domain: req.headers.host ?? "",
method: req.method,
url: `${req.protocol}://${req.headers.host}${req.originalUrl}`,
path: req.path,
status_code: res.statusCode,
response_time_ms: Date.now() - start,
user_agent: req.headers["user-agent"] ?? "",
ip_address: anonymizeIp(
(req.headers["x-forwarded-for"] as string)?.split(",")[0]?.trim() ??
req.ip ??
"",
),
referrer: (req.headers.referer as string) ?? "",
referrer_domain: "",
headers: {},
query_parameters: {},
utm_source: "",
utm_medium: "",
utm_campaign: "",
utm_term: "",
utm_content: "",
} satisfies CapturedRequest;
const payload = buildEventPayload(captured, process.env.SEARCHABLE_SITE_TOKEN!);
// Fire-and-forget — don't await
void sendEvent(payload, {
siteToken: process.env.SEARCHABLE_SITE_TOKEN!,
apiKey: process.env.SEARCHABLE_API_KEY!,
});
});
next();
});
```
### Fastify
```ts server.ts theme={null}
import Fastify from "fastify";
import {
buildEventPayload,
sendEvent,
anonymizeIp,
} from "@searchablehq/middleware";
const app = Fastify();
app.addHook("onResponse", async (request, reply) => {
const captured = {
domain: request.headers.host ?? "",
method: request.method,
url: `${request.protocol}://${request.headers.host}${request.url}`,
path: request.url.split("?")[0],
status_code: reply.statusCode,
response_time_ms: reply.elapsedTime,
user_agent: request.headers["user-agent"] ?? "",
ip_address: anonymizeIp(request.ip),
referrer: (request.headers.referer as string) ?? "",
referrer_domain: "",
headers: {},
query_parameters: {},
utm_source: "",
utm_medium: "",
utm_campaign: "",
utm_term: "",
utm_content: "",
};
const payload = buildEventPayload(
captured,
process.env.SEARCHABLE_SITE_TOKEN!,
);
void sendEvent(payload, {
siteToken: process.env.SEARCHABLE_SITE_TOKEN!,
apiKey: process.env.SEARCHABLE_API_KEY!,
});
});
```
Always call `sendEvent` after the response is finalised (`res.on("finish")`, `onResponse`, …). Doing it earlier slows down the response, and `status_code` / `response_time_ms` won't be accurate.
## What gets captured
For every non-static request the SDK records:
* HTTP method, path, URL, status code, response time
* User agent (used by Searchable to classify the AI bot)
* Anonymised IP (zero last octet by default — toggle via `anonymizeIp: false`)
* Referrer + parsed referrer domain
* UTM parameters extracted from the URL
* Geo location (country, region, city) when your edge runtime exposes it (e.g. Next.js Edge Runtime)
* Filtered request headers — only an allowlist of safe ones (`accept-language`, `host`, `sec-ch-ua*`, etc.)
* Non-UTM query parameters
* Anything you return from `custom(request)`
Cookies, request/response bodies, and full IP addresses are never sent. Sensitive headers (`authorization`, `cookie`, `set-cookie`, `x-api-key`, `proxy-authorization`, `x-forwarded-for`, `x-real-ip`) are stripped at the edge before the worker forwards events to ingest.
## Verifying the connection
In Searchable:
1. Go to **LLM Analytics → Setup**
2. The **Custom** card's status indicator should flip to **Connected** once the first event arrives
3. Hit your site with `curl` using a known AI user agent to force one:
```bash theme={null}
curl -H "User-Agent: GPTBot/1.0 (+https://openai.com/gptbot)" \
https://yourdomain.com/
```
| Status | What it means |
| --------------------------- | --------------------------------------------------------------------------------------- |
| **Waiting for first event** | The middleware is deployed but no AI bot has been seen yet. Curl an AI UA to force one. |
| **Connected** | Events are arriving. The count from the last 24 hours is shown alongside. |
Add `debug: true` locally to confirm events are firing without leaving your dev environment.
## Troubleshooting
Most often the request never reaches Searchable because the middleware isn't running on the routes AI bots hit.
* Check your `config.matcher` actually covers the live URLs — Next's default skips `_next/*` but you might be excluding more than intended
* Confirm `SEARCHABLE_SITE_TOKEN` and `SEARCHABLE_API_KEY` are set in the deployed environment (not just locally)
* Set `debug: true`, redeploy, and check your logs — the SDK logs every event it sends
* Curl your live domain with `User-Agent: GPTBot/1.0` and re-check the status
Searchable filters non-bot user agents server-side. If your test request used a normal browser UA, it's discarded silently. Use a known AI UA:
```bash theme={null}
curl -H "User-Agent: GPTBot/1.0 (+https://openai.com/gptbot)" https://yourdomain.com/
```
Other supported test UAs: `ClaudeBot/1.0`, `PerplexityBot/1.0`, `Google-Extended/1.0`.
The API key is missing or wrong:
* Confirm `SEARCHABLE_API_KEY` starts with `sk_live_` and has no leading/trailing whitespace
* If you've recently revoked the key in Searchable, generate a new one and update your env
* The key must have the **Log Events** permission. Re-create it from the Custom connector dialog if unsure — that's the default permission for keys generated there.
Set different values for `SEARCHABLE_SITE_TOKEN` in your staging and production environments. Site tokens are per-project — staging traffic going to a staging project keeps your production data clean.
The same workspace `SEARCHABLE_API_KEY` works across all projects in a workspace as long as it isn't project-scoped. To scope a key to a single project, generate it from inside that project's Custom connector dialog.
Override the endpoint via `endpoint` and point at a path your CDN forwards untouched, or route the SDK's POST through a server-side proxy that re-adds the header.
## Removing the integration
1. Delete the `withSearchable(...)` call (or pass through the inner middleware only)
2. Remove `SEARCHABLE_SITE_TOKEN` and `SEARCHABLE_API_KEY` from your env
3. In Searchable → **Settings → API Keys** → revoke the API key
Revoking the key alone is enough to stop ingestion immediately — every in-flight POST starts failing with 403 — even if the SDK is still deployed.
## Next steps
Want the raw HTTP shape, or instrument a non-Node stack?
Open LLM Analytics to see which assistants are crawling your site.
# Send Netlify traffic to Searchable (HTTP Log Drain)
Source: https://docs.searchable.com/setup/netlify-drain
Configure a Netlify HTTP Log Drain to stream request logs to Searchable. No code changes — all configuration is done inside the Netlify dashboard.
## What this does
Netlify's HTTP Log Drain streams every inbound request log entry to a destination of your choosing. We point that drain at Searchable's ingest endpoint, classify the AI bots, and drop everything else.
**No code changes.** All configuration is done inside the Netlify dashboard.
**Enterprise plan only.** HTTP Log Drains are a Netlify Enterprise feature. If you're on a Free, Pro, or Business plan, use the **[Edge Function](/setup/netlify-edge)** path instead — it works on all plans.
## Prerequisites
A Netlify team on the Enterprise plan
Team Owner access in Netlify (Log Drain settings are team-level)
A Searchable project with your domain confirmed
## Setup
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Netlify Log Drain** as your crawler source
4. Click **Generate token**
Copy the token now — it starts with `sa_…` and won't be shown again. You can always generate a new one if you lose it.
Navigate to your Netlify team:
**Team settings → Log drains → Add log drain**
This setting is team-level, not site-level. You need Team Owner access to see it.
Fill in these fields:
| Field | Value |
| ----------------------- | --------------------------------------------------------- |
| **Service** | HTTPS endpoint |
| **Endpoint URL** | `https://tracker.searchableanalytics.com/v1/netlify-logs` |
| **Format** | JSON (Netlify delivers NDJSON over HTTPS) |
| **Custom header name** | `Authorization` |
| **Custom header value** | `Bearer ` |
The custom header value must be `Bearer ` followed by the full `sa_…` token, with one space and no quotes. The header name must be exactly `Authorization`.
Click **Save**. Netlify sends a verification ping to the endpoint — Searchable accepts it.
Then return to **LLM Analytics → Setup** in Searchable. The Netlify Log Drain card should show **Connected** within a few minutes once an AI bot hits your site.
## Verifying the connection
In Searchable:
1. Go to **LLM Analytics → Setup**
2. Look at the Netlify Log Drain card status
3. Click **Check** if it still shows "Waiting for first event"
| Status | What it means |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Waiting for first event** | The drain is configured but no AI bot has hit your site yet. Typical wait is a few hours for sites that are already indexed. |
| **Connected** | Events are arriving. The card shows the count from the last 24 hours. |
## Troubleshooting
The Authorization header is missing or wrong.
* Make sure you added a **custom header** named exactly `Authorization`
* The value must be `Bearer ` followed by the full `sa_…` token, with one space and no quotes
* If you've recently revoked the token in Searchable, generate a new one and update the drain
Check the drain format setting.
* The format must be set to **JSON** (which delivers NDJSON over HTTPS) — not Datadog, Splunk, or any other structured format
* If the format was wrong, update it and save — Netlify will retry pending deliveries
Log Drains are only visible to Team Owners on the Enterprise plan. If you don't see **Team settings → Log drains**:
* Confirm you have Team Owner access (not just Member)
* Confirm your Netlify team is on the Enterprise plan
If you're not on Enterprise, use the **[Edge Function](/setup/netlify-edge)** path — it works on all plans and requires no Netlify plan upgrade.
A few possible causes:
* The drain isn't enabled or is paused — check Netlify's Team settings → Log drains
* Your domain in Searchable doesn't match the site on Netlify (check **LLM Analytics → Setup → Confirm your domain**)
* The drain is configured but no AI bot has visited yet — try visiting your site with a known AI user agent to trigger a test event
If deliveries are succeeding in Netlify but nothing appears in Searchable, that points to a domain mismatch.
## Removing the integration
To stop sending traffic to Searchable:
1. Netlify → **Team settings → Log drains** → delete the drain
2. Searchable → **LLM Analytics → Setup → Tokens** → revoke the token
Both sides are independent — revoking the token alone is enough to stop ingestion immediately, even if the drain stays configured in Netlify (its deliveries will start returning `401`).
## Next steps
Open LLM Analytics to see which assistants are crawling your site.
Correlate AI crawls with search demand.
# Send Netlify traffic to Searchable (Edge Function)
Source: https://docs.searchable.com/setup/netlify-edge
Forward AI-bot traffic from your Netlify-hosted site to Searchable using a small Edge Function that runs on every request. Works on every Netlify plan, including Free.
## What this does
An Edge Function runs at Netlify's edge in front of your origin. For every inbound request it:
1. Lets the request pass through to your origin unchanged (no added latency for users)
2. After the response is returned, fires a fire-and-forget POST to Searchable with the request metadata
3. Returns the original response to the visitor
Searchable classifies the user agent server-side and records it if it matches a known AI crawler.
**Works on every Netlify plan, including Free.** Netlify's free plan covers 1M Edge Function invocations per month — well above typical bot traffic for most sites.
## Prerequisites
A Netlify site with deploy access
A Searchable project with your domain confirmed
## Setup
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Netlify Edge Function** as your crawler source
4. Click **Generate token**
Copy the token now — it starts with `sa_…` and won't be shown again. You can always generate a new one if you lose it.
Create the file `netlify/edge-functions/searchable.ts` in your repository and paste the snippet below.
```typescript netlify/edge-functions/searchable.ts theme={null}
import type { Context } from "https://edge.netlify.com";
const ENDPOINT = "https://tracker.searchableanalytics.com/v1/netlify-edge";
const TOKEN = Netlify.env.get("SEARCHABLE_TOKEN");
export default async function (request: Request, context: Context) {
const response = await context.next();
context.waitUntil(forward(request, response, context));
return response;
}
async function forward(request: Request, response: Response, context: Context) {
if (!TOKEN) return;
try {
const url = new URL(request.url);
await fetch(ENDPOINT, {
method: "POST",
headers: { "content-type": "application/json", authorization: `Bearer ${TOKEN}` },
body: JSON.stringify({
type: "netlify_edge_event",
timestamp: Date.now(),
request_id: request.headers.get("x-nf-request-id") ?? crypto.randomUUID(),
method: request.method,
path: url.pathname,
url: request.url,
status_code: response.status,
user_agent: request.headers.get("user-agent") ?? "",
ip_address: context.ip ?? "",
country: context.geo?.country?.code ?? "",
referrer: request.headers.get("referer") ?? "",
}),
});
} catch {
/* swallow */
}
}
export const config = { path: "/*" };
```
The function intercepts every request, forwards a lightweight event to Searchable after the response is returned, and never blocks the user.
In your Netlify site:
**Site settings → Environment variables → Add a variable**
| Key | Value |
| ------------------ | ------------------------------------ |
| `SEARCHABLE_TOKEN` | The `sa_…` token you generated above |
Make sure the variable name is exactly `SEARCHABLE_TOKEN` (all caps, underscore).
Commit the new file and push to your main branch. Netlify will auto-deploy the edge function.
```bash theme={null}
git add netlify/edge-functions/searchable.ts
git commit -m "Add Searchable edge function"
git push
```
In Netlify, open **Site settings → Edge functions** and confirm that `searchable` appears in the list and is marked active.
## Verifying the connection
Return to **LLM Analytics → Setup** in your Searchable dashboard. The Netlify Edge Function card should flip to **Connected** within about 10 seconds of the next AI crawler hitting your site.
| Status | What it means |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **Waiting for first event** | The function is deployed but no AI bot has hit your site yet. Typical wait is a few hours for sites that are already indexed. |
| **Connected** | Events are arriving. The card shows the count from the last 24 hours. |
## Cost
Each forwarded request consumes one Edge Function invocation. Netlify's free plan covers 1M invocations per month — bot traffic is a tiny fraction of that for typical sites.
## Troubleshooting
Check these in order:
* The environment variable is named exactly `SEARCHABLE_TOKEN` (all caps, underscore — not `SearchableToken` or `SEARCHABLE-TOKEN`)
* The deploy succeeded — check Netlify's deploy log for errors in the edge function
* The function is active in **Site settings → Edge functions**
* The `config` export at the bottom of the file sets `path: "/*"` so the function runs on all requests
That's expected. Searchable filters non-bot user agents server-side — only AI crawlers (GPTBot, ClaudeBot, PerplexityBot, etc.) are recorded in your dashboard. Human visitors are forwarded but immediately discarded.
If the function throws during `context.next()`, Netlify may surface it in deploy logs. The `forward()` call is wrapped in a `try/catch` and uses `context.waitUntil(...)`, so errors inside `forward` are silently swallowed and never affect your visitors.
Confirm the function file is valid TypeScript and that the `import type { Context }` line is present — Netlify's Deno runtime requires it.
## Removing the integration
1. Delete `netlify/edge-functions/searchable.ts` from your repo and push
2. Netlify → **Site settings → Environment variables** → remove `SEARCHABLE_TOKEN`
3. Searchable → **LLM Analytics → Setup → Tokens** → revoke the token
## Next steps
Open LLM Analytics to see which assistants are crawling your site.
Correlate AI crawls with search demand.
# LLM Analytics Setup
Source: https://docs.searchable.com/setup/overview
Connect your hosting platform to Searchable so we can show you which AI assistants and crawlers are visiting your site
## What this does
Searchable's LLM Analytics dashboard shows you, in near real-time, which AI assistants — ChatGPT, Claude, Perplexity, Google's AI Overviews, and the rest — are crawling your site, what pages they're hitting, and which of those crawls turn into referred users.
To do that, Searchable needs to see your inbound HTTP requests. The setup below points your hosting platform's request logs at our ingest endpoint. We classify the AI bots, drop everything else, and never store query strings or other PII.
Setup takes about 5 minutes. There are no agents to install and no code to change in your application.
## Pick your platform
One-click Log Drain. Works on Pro and Enterprise.
Edge Worker — works on any Cloudflare plan, including Free.
Native Logpush job — Enterprise plan only.
Standard Logging V2 via Firehose — any CloudFront distribution.
Edge Function — works on every Netlify plan, including Free.
HTTP Log Drain — Enterprise plan only.
Real-Time Log Streaming via HTTPS endpoint.
DataStream 2 HTTPS push — any property with DataStream 2 entitled.
HTTPS Load Balancer / Cloud CDN logs via Pub/Sub push.
Custom REST API or middleware for everything else.
## Which one should I use?
Use **[Vercel Log Drain](/setup/vercel)**. It's the most direct path — Vercel streams request logs to Searchable with one entry in your project settings. No code changes.
Use the **[Cloudflare Worker](/setup/cloudflare-worker)**. It works on every Cloudflare plan including Free, and the Free tier easily covers \~100k requests/day. The Worker forwards AI-bot traffic to Searchable from the edge — no latency added to real users.
You can use either path. **[Cloudflare Logpush](/setup/cloudflare)** is the most "native" option — Cloudflare batches and ships logs directly with no Worker involved. If you'd rather avoid the Enterprise-only Logpush feature, the **[Worker](/setup/cloudflare-worker)** path works on Enterprise too.
Use **[Amazon CloudFront → Firehose](/setup/cloudfront)**. CloudFront's free Standard Logging V2 feature ships records to Amazon Data Firehose, which forwards them to Searchable. Works on any CloudFront distribution — you only pay for the Firehose ingestion.
Use the **[Netlify Edge Function](/setup/netlify-edge)** on any plan (including Free), or **[Netlify Log Drain](/setup/netlify-drain)** if you're on the Enterprise plan. The Edge Function path runs at Netlify's edge with no added latency for real users.
Use **[Fastly Real-Time Log Streaming](/setup/fastly-logs)**. Configure an HTTPS Logging endpoint inside the Fastly UI — no code changes — and Fastly streams request logs to Searchable.
Use **[Akamai DataStream 2](/setup/akamai-datastream2)**. Create a DataStream 2 stream in Akamai Control Center, pick the property fronting your domain, and point it at Searchable's HTTPS endpoint. Requires the DataStream 2 product on your Akamai contract — your account team can confirm if it's enabled.
Use **[Google Cloud → Pub/Sub push](/setup/gcp-logs)**. Cloud Logging captures every HTTPS Load Balancer or Cloud CDN request; a Pub/Sub topic with a push subscription forwards those logs to Searchable.
Use the **[custom integration](/setup/custom)**. Searchable accepts a small REST POST from your application middleware or any platform that can ship structured request logs.
## What gets sent to Searchable
For each request that matches an AI-bot user agent, we receive:
* HTTP method, path, and host (no query strings)
* User agent
* Referer
* Country code (geo-IP, no precise location)
* Response status and bytes
* Timestamp
That's it. Query strings, request bodies, response bodies, headers other than `User-Agent` / `Referer`, and full IP addresses are never sent.
## Verifying the connection
After completing setup, return to **LLM Analytics → Setup** in your Searchable dashboard. The status strip at the bottom updates as events arrive:
1. **Waiting for first event** — your platform hasn't sent anything yet. AI bots typically hit any indexed site within a few hours.
2. **Connected** — events are flowing. The strip shows the count from the last 24 hours.
If the status doesn't update within a few hours, see the troubleshooting section in the platform-specific guide you followed.
## Next steps
LLM Analytics is scoped to your project's primary domain.
Layer in keyword data so you can correlate AI crawls with search demand.
# Send traffic to Searchable via the REST API
Source: https://docs.searchable.com/setup/rest-api
Send AI-bot traffic events to Searchable from any language or platform — a single HTTP POST with a signed Bearer token.
## What this is
Searchable's REST API is the language-agnostic way to ship request events from your app. It's a single `POST` to a Cloudflare-hosted ingest endpoint with an `Authorization: Bearer sk_live_…` header and a JSON body of one or more events. The server-side AI-bot classifier filters non-AI user agents, so even if you POST every request from your app, only crawlers like GPTBot, ClaudeBot, and PerplexityBot end up in your dashboard.
**Use this when the [Middleware SDK](/setup/middleware) doesn't fit** — non-Node stacks, in-house CDN workers, batch jobs that replay logs, or anywhere you want fine-grained control over the payload.
## Prerequisites
The two credentials from the [common prerequisites](/setup/custom#common-prerequisites): a project **site token** (`st_…`) and a workspace **API key** (`sk_live_…`)
Any runtime that can make an authenticated HTTPS POST — `curl`, `fetch`, `requests`, Go's `net/http`, etc.
## Endpoint
```
POST https://tracker.searchableanalytics.com/v1/events
```
Requests are authenticated, verified, and forwarded at Cloudflare's edge — there's no DB round-trip on the auth path, so you can call this from latency-sensitive contexts.
| Header | Value |
| --------------- | ------------------------------------------ |
| `Authorization` | `Bearer sk_live_…` — the workspace API key |
| `Content-Type` | `application/json` |
## Request body
```json theme={null}
{
"site_token": "st_your_token_here",
"events": [
{
"event_name": "server_request",
"timestamp": 1716105600000,
"method": "GET",
"path": "/blog/my-post",
"url": "https://example.com/blog/my-post",
"status_code": 200,
"response_time_ms": 42,
"user_agent": "GPTBot/1.0",
"referrer": "",
"ip_address": "203.0.113.42",
"country": "US"
}
]
}
```
### Top-level fields
| Field | Type | Required | Description |
| ------------ | ------ | -------- | ------------------------------------------------------------------ |
| `site_token` | string | yes | The project's private site token (starts with `st_`) |
| `events` | array | yes | One or more event objects. Batch up to 1MB of payload per request. |
### Event fields
| Field | Type | Required | Description |
| --------------------------------------------------------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------ |
| `event_name` | string | yes | Use `"server_request"` for HTTP request events |
| `timestamp` | number | yes | Unix timestamp in **milliseconds** |
| `method` | string | yes | HTTP method (`GET`, `POST`, …) |
| `path` | string | yes | Request path. Query strings are stripped server-side. |
| `url` | string | yes | Full request URL |
| `status_code` | number | yes | HTTP response status |
| `response_time_ms` | number | yes | Server response time in milliseconds |
| `user_agent` | string | — | User-Agent header. Empty string if unavailable. |
| `ip_address` | string | — | Client IP. Defaults to `0.0.0.0` if omitted. We recommend anonymizing the last octet client-side. |
| `referrer` | string | — | HTTP Referer header |
| `referrer_domain` | string | — | Pre-parsed referrer hostname (we'll derive it from `referrer` if omitted) |
| `country` | string | — | 2-letter ISO country code (e.g. `US`). Geo enrichment otherwise comes from Cloudflare's edge metadata. |
| `region` | string | — | Region / state code |
| `city` | string | — | City name |
| `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content` | string | — | Standard UTM fields |
| `headers` | object | — | Map of safe request headers you want to retain |
| `query_parameters` | object | — | Non-UTM query parameters as a string map |
| `custom_properties` | object | — | Arbitrary string-keyed properties exposed as `parameters` in the dashboard |
Unknown fields are ignored. Fields with bad types are coerced where safe (counts → unsigned int, status codes → uint).
## Response
| Status | Meaning |
| ----------------------- | ---------------------------------------------------------------- |
| `202 Accepted` | Events were accepted and forwarded to ingest. The body is empty. |
| `400 Bad Request` | Body wasn't valid JSON, or `events` wasn't an array. |
| `401 Unauthorized` | Missing `Authorization` header. |
| `403 Forbidden` | Token signature invalid, or `site_token` missing from body. |
| `413 Payload Too Large` | Request body exceeded 1 MB. Split your batch. |
`202` is the success status — events are accepted and dispatched asynchronously. There is no synchronous confirmation that an event reached ClickHouse; use the **LLM Analytics → Setup** status strip to verify end-to-end flow.
## Quick start — `curl`
```bash theme={null}
curl -X POST https://tracker.searchableanalytics.com/v1/events \
-H "Authorization: Bearer sk_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"site_token": "st_YOUR_SITE_TOKEN",
"events": [{
"event_name": "server_request",
"timestamp": '"$(date +%s%3N)"',
"method": "GET",
"path": "/blog/my-post",
"url": "https://example.com/blog/my-post",
"status_code": 200,
"response_time_ms": 42,
"user_agent": "GPTBot/1.0"
}]
}'
```
A successful call returns an empty body and `202 Accepted`. Within a few seconds, the **Custom** card in **LLM Analytics → Setup** flips to **Connected**.
## Examples
### Node — `fetch`
```ts theme={null}
async function reportRequest(req: {
method: string;
path: string;
url: string;
status: number;
durationMs: number;
userAgent: string;
}) {
await fetch("https://tracker.searchableanalytics.com/v1/events", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SEARCHABLE_API_KEY!}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
site_token: process.env.SEARCHABLE_SITE_TOKEN!,
events: [
{
event_name: "server_request",
timestamp: Date.now(),
method: req.method,
path: req.path,
url: req.url,
status_code: req.status,
response_time_ms: req.durationMs,
user_agent: req.userAgent,
},
],
}),
}).catch(() => {
// Fire-and-forget. Never fail the user's request on a Searchable error.
});
}
```
Don't `await` this from a request handler in latency-sensitive paths — either fire it after the response is flushed, or push it onto a worker queue.
### Python — `requests`
```python theme={null}
import os
import time
import requests
def report_request(method, path, url, status, duration_ms, user_agent):
payload = {
"site_token": os.environ["SEARCHABLE_SITE_TOKEN"],
"events": [{
"event_name": "server_request",
"timestamp": int(time.time() * 1000),
"method": method,
"path": path,
"url": url,
"status_code": status,
"response_time_ms": duration_ms,
"user_agent": user_agent,
}],
}
try:
requests.post(
"https://tracker.searchableanalytics.com/v1/events",
json=payload,
headers={"Authorization": f"Bearer {os.environ['SEARCHABLE_API_KEY']}"},
timeout=2,
)
except requests.RequestException:
pass # fire-and-forget
```
### Go — `net/http`
```go theme={null}
package searchable
import (
"bytes"
"context"
"encoding/json"
"net/http"
"os"
"time"
)
type Event struct {
EventName string `json:"event_name"`
Timestamp int64 `json:"timestamp"`
Method string `json:"method"`
Path string `json:"path"`
URL string `json:"url"`
StatusCode int `json:"status_code"`
ResponseTimeMs int `json:"response_time_ms"`
UserAgent string `json:"user_agent"`
}
type Payload struct {
SiteToken string `json:"site_token"`
Events []Event `json:"events"`
}
func Report(ctx context.Context, e Event) error {
body, _ := json.Marshal(Payload{
SiteToken: os.Getenv("SEARCHABLE_SITE_TOKEN"),
Events: []Event{e},
})
req, _ := http.NewRequestWithContext(ctx, "POST",
"https://tracker.searchableanalytics.com/v1/events",
bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("SEARCHABLE_API_KEY"))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 2 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
}
resp.Body.Close()
return nil
}
```
## Batching
The endpoint accepts up to 1 MB per request and any number of events in the `events` array. For high-volume sources, batch events on a short flush interval (e.g. every 5 s or every 100 events) rather than sending one POST per request — fewer network round-trips, same data.
Each event in a batch is independent; ingest validates and persists them individually, so a single malformed event doesn't drop the rest of the batch.
## What gets recorded
Even though you can post any HTTP request through this endpoint, Searchable's server-side classifier only records events whose `user_agent` matches a known AI crawler. Everything else is dropped silently.
That's intentional: it lets you instrument your app once and not worry about which UAs to filter in your code. The bot list is refreshed daily — new AI agents are picked up automatically.
You can sanity-check the classifier against the public bot artifact at:
```
GET https://tracker.searchableanalytics.com/v1/bots.json
```
That's the same list the worker uses internally — useful if you want to do client-side filtering to reduce ingest load.
## Verifying the connection
In Searchable:
1. Go to **LLM Analytics → Setup**
2. Hit the endpoint with a known AI user agent to force a first event (see the [`curl` example](#quick-start-curl))
3. Click **Refresh** in the status strip
| Status | What it means |
| --------------------------- | ------------------------------------------------------------------------- |
| **Waiting for first event** | API key + body are valid but no event has matched the bot classifier yet. |
| **Connected** | Events are arriving. The strip shows the count from the last 24 hours. |
## Troubleshooting
The `Authorization` header is missing.
* Check the header is named exactly `Authorization` (not `authorisation`, `X-Authorization`, etc.)
* The value must be `Bearer ` followed by your `sk_live_…` key, with one space and no quotes
* Some CDNs strip `Authorization` on internal hops — verify the header is present when the request leaves your edge
The API key's signature failed verification.
* Confirm you copied the key in full — it's two URL-safe base64 segments separated by a `.`
* If you've recently revoked the key in Searchable, generate a new one (Settings → API Keys → New key)
* Make sure you're using a key with the **Log Events** permission — generating from the Custom connector dialog assigns it by default
The body must include `site_token` at the top level. Don't put it inside an event object.
```json theme={null}
{ "site_token": "st_…", "events": [ /* … */ ] }
```
`events` must be an array, even for a single event. Wrap your event in `[ … ]`:
```json theme={null}
{ "site_token": "st_…", "events": [ { /* event */ } ] }
```
Request body exceeded 1 MB. Either split into multiple POSTs, or trim large fields (headers, query parameters, custom properties) from each event.
The classifier is dropping them because the `user_agent` isn't a known AI crawler. Use an AI UA in your test:
```bash theme={null}
curl -H "User-Agent: GPTBot/1.0 (+https://openai.com/gptbot)" ...
```
Or fetch the live AI-bot list and confirm your UA matches one of the patterns:
```bash theme={null}
curl https://tracker.searchableanalytics.com/v1/bots.json
```
## Removing the integration
1. Stop sending POSTs from your app
2. In Searchable → **Settings → API Keys** → revoke the API key
Revoking the key is the cleanest stop — every subsequent POST returns 403, regardless of where it's coming from.
## Next steps
On Node? The SDK is one import and handles the payload for you.
Open LLM Analytics to see which assistants are crawling your site.
# Send Vercel traffic to Searchable
Source: https://docs.searchable.com/setup/vercel
Stream your Vercel project's request logs to Searchable using a Log Drain — no code changes, takes about 3 minutes
## What this does
Vercel's [Log Drain](https://vercel.com/docs/observability/log-drains) feature streams every inbound request to a destination of your choosing. We point that drain at Searchable's ingest endpoint, classify the AI bots, and drop everything else.
**No code changes.** All configuration is done inside the Vercel dashboard.
## Prerequisites
A Vercel project on the Pro or Enterprise plan (Log Drains aren't available on Hobby)
Owner or Member-with-admin access to the Vercel project
A Searchable project with your domain confirmed
## Setup
1. Open your Searchable dashboard
2. Go to **LLM Analytics → Setup**
3. Pick **Vercel** as your crawler source
4. Click **Generate token**
Copy the token now — it starts with `sa_…` and won't be shown again. You can always generate a new one if you lose it.
Navigate to your Vercel project:
**Project Settings → Log Drains → Add**
Or open it directly: [vercel.com/dashboard/log-drains](https://vercel.com/dashboard/log-drains)
Fill in these fields:
| Field | Value |
| ------------------- | ------------------------------------------------------------ |
| **Delivery format** | NDJSON |
| **Endpoint** | `https://tracker.searchableanalytics.com/v1/vercel-logs` |
| **Custom headers** | `Authorization: Bearer ` |
| **Sources** | Functions, Edge Functions, Static Files, Firewall, Redirects |
| **Sampling rate** | 100% |
Selecting all five sources is what gives Searchable a complete picture. AI crawlers hit static files (sitemaps, robots.txt) almost as often as they hit pages.
Click **Save**. Vercel sends a verification ping to the endpoint immediately — Searchable accepts it.
Then return to **LLM Analytics → Setup** in Searchable. The status strip at the bottom should show **Connected** within a few minutes once an AI bot hits your site.
## What Searchable receives
For each request, the Log Drain sends a small NDJSON record with:
* HTTP method, path, host (query strings stripped before storage)
* User agent
* Referer
* Status code, response bytes
* Timestamp
* Geo country (from Vercel's edge metadata)
Bodies, headers, cookies, and full IPs are never sent or stored.
## Verifying the connection
In Searchable:
1. Go to **LLM Analytics → Setup**
2. Look at the status strip at the bottom of the page
3. Click **Check** if it still shows "Waiting for first event"
| Status | What it means |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Waiting for first event** | The drain is configured but no AI bot has hit your site yet. Typical wait is a few hours for sites that are already indexed. |
| **Connected** | Events are arriving. The strip shows the count from the last 24 hours. |
You can also confirm in Vercel: **Log Drains → your drain → Deliveries**. Successful deliveries return `204 No Content`.
## Troubleshooting
The Authorization header is missing or wrong.
* Make sure you added a **custom header** (not a query parameter) named exactly `Authorization`
* The value must be `Bearer ` followed by the full `sa_…` token, with one space and no quotes
* If you've recently revoked the token in Searchable, generate a new one and update the drain
The delivery format isn't NDJSON.
* In the drain settings, set **Delivery format** to `NDJSON` (not JSON or Logfmt)
* Save the drain — Vercel will retry pending deliveries
A few possible causes:
* The drain isn't enabled (check Vercel — drains can be paused)
* The selected sources don't include the routes AI bots are hitting (re-check **Sources** includes Static Files and Functions)
* Your domain in Searchable doesn't match the project on Vercel (check **LLM Analytics → Setup → Confirm your domain**)
If everything looks right, Vercel's **Deliveries** tab tells you whether deliveries are succeeding. Successful deliveries that don't appear in Searchable point to a domain mismatch.
Log Drains are a Pro / Enterprise feature on Vercel. On Hobby, your options are:
* Upgrade Vercel to Pro
* Use the **[Cloudflare Worker](/setup/cloudflare-worker)** path if your domain sits behind Cloudflare
* Use the **[custom REST API](/setup/custom)** path with Next.js middleware
## Removing the integration
To stop sending traffic to Searchable:
1. Vercel → **Project Settings → Log Drains** → delete the drain
2. Searchable → **LLM Analytics → Setup → Tokens** → revoke the token
Both sides are independent — revoking the token alone is enough to stop ingestion immediately, even if the drain stays configured in Vercel (its deliveries will start returning `401`).
## Next steps
Open LLM Analytics to see which assistants are crawling your site.
Correlate AI crawls with search demand.
# Use Cases
Source: https://docs.searchable.com/use-cases
Paste-ready prompts for the Searchable MCP — weekly AI visibility briefs, competitor watch, citation gap analysis, and more.
Searchable's MCP server turns your AI visibility, competitive, and content data into paste-ready prompts for Claude, ChatGPT, Cursor, and any other MCP-compatible assistant. Every prompt below is copy-paste-ready into a connected assistant and names the underlying Searchable MCP tools it exercises (the **Uses** line), so you know what's actually being queried before you run it.
Not connected yet? See the [MCP integration guide](/integrations/mcp) to add the Searchable server to your assistant in a few minutes.
## Reporting
### Weekly AI Visibility Brief
**Category:** Reporting · **Uses:** `get_visibility` (incl. `group_by: "date"` for the trend), `get_share_of_voice`, `search_sources`, `get_sentiment`, `generate_report`
A full week-in-review — score, trend, share of voice, top sources, and sentiment — synthesized into a short narrative and published as a shareable link, without leaving your assistant.
```
Using the Searchable MCP, pull my brand's AI visibility score and trend for
the last 7 days, our share of voice against tracked competitors, our top
cited sources, and our sentiment breakdown. Summarize it as a short weekly
brief with one recommended focus for the week, then generate a shareable
report and give me the link.
```
### Kick Off a Technical + AEO Audit
**Category:** Reporting · **Uses:** `trigger_audit`, `get_site_health`
Start a technical + AEO audit on your tracked pages and pull the resulting scores and open issues in one pass.
*`trigger_audit` requires a grant or key with the **write** scope.*
```
Using the Searchable MCP, start a technical and AEO audit for my project
(confirm it so it actually runs), then summarize the current site health —
scores by page and any critical or high-severity issues.
```
## Analysis
### Find Uncited Topics on ChatGPT
**Category:** Analysis · **Uses:** `search_sources`, `get_source_detail`
Spot which sites ChatGPT leans on for your tracked topics — and which of those never mention your brand.
```
Using the Searchable MCP, show me the top source domains ChatGPT cites for
my tracked topics, then check a few of the highest-citation ones to see
which don't mention our brand at all.
```
### Spot-Check a Prompt's AI Answers
**Category:** Analysis · **Uses:** `get_visibility`, `get_prompt_answers`
Go from "which prompt is weakest" to "what did the AI actually say" in two calls.
```
Using the Searchable MCP, find our lowest mention-rate prompt from the last
30 days and show me the actual AI answers for it — did we get mentioned,
who else did, and what got cited.
```
### Google Search Console Quick Wins
**Category:** Analysis · **Uses:** `get_gsc_performance`
Surface the queries closest to a click-through breakthrough — ranking well, barely getting clicked.
```
Using the Searchable MCP, pull our Google Search Console quick-win queries
— ranking positions 4 through 15 with decent impressions but low
click-through rate — for the last 30 days.
```
## Monitoring
### Competitor Movement Briefing
**Category:** Monitoring · **Uses:** `get_competitors`, `get_share_of_voice`, `get_sentiment`, `get_visibility`
A recurring check on tracked competitors — share-of-voice and sentiment moves worth knowing about, not just a data dump.
```
Using the Searchable MCP, check our tracked competitors for meaningful
share-of-voice or sentiment movement since yesterday and flag anything
worth our attention.
```
### Check Shopping Carousel Visibility
**Category:** Monitoring · **Uses:** `get_shopping_visibility`
A quick pulse check on whether your products are showing up in AI shopping answers at all.
```
Using the Searchable MCP, check whether our products are showing up in AI
shopping and product-carousel answers this month, and tell me our
activation rate and top-ranked products.
```
### AI Referral Traffic Pulse
**Category:** Monitoring · **Uses:** `get_ai_traffic`
First-party crawler and referral traffic from AI platforms, at a glance.
```
Using the Searchable MCP, give me an overview of AI crawler and
AI-referral traffic for the last 30 days — totals by platform and our top
crawled pages.
```
## Content
### Close Citation Gaps Against Competitors
**Category:** Content · **Uses:** `get_competitors`, `get_share_of_voice`, `search_sources`, `get_source_detail`, `get_source_trends`
Find the sites already citing your competitors in AI answers, confirm you're genuinely absent, and rank them into an outreach and content list.
```
Using the Searchable MCP, find the source domains that cite my competitors
in AI answers but rarely or never cite us, and turn that into a
prioritized outreach and content list.
```
### Content Brief From Prompt Gaps
**Category:** Content · **Uses:** `get_visibility`, `get_prompt_answers`, `get_query_fanout`
Turn your zero-visibility prompts into ready-to-write content briefs, grounded in what AI models actually ask and who currently wins the citation.
```
Using the Searchable MCP, find the tracked prompts where our brand has
close to 0% mention rate, show me which competitors get cited instead,
and write a content brief for each gap covering the sub-topics AI models
actually ask about.
```
***
*Four of these workflows (the Weekly AI Visibility Brief, Competitor Movement Briefing, Close Citation Gaps Against Competitors, and Content Brief From Prompt Gaps) are also packaged as reusable Agent Skills for MCP clients that support the Agent Skills format — check back soon as we publish them to the public Agent Skills directories.*
# AI-Powered Content Generation
Source: https://docs.searchable.com/using-searchable/content-generation
Generate optimized content that ranks in both traditional search and AI responses
## Overview
Searchable's AI content generator creates high-quality, SEO and AEO-optimized articles based on your target keywords and prompts. Generate content that not only ranks in Google but also gets cited by AI models like ChatGPT and Claude.
Ranked List, Topic Guide, Comparison, How-to Guide, Alternatives Guide
Let the Agent know what kind of post you'd like to write
AI analyzes current trends, competitor content, and search patterns
AI creates the article outline for you to review and modify
AI creates optimized content with proper citations and structure
Review the generated content and publish directly to your platform
## Content Generation Process
Select from:
* Ranked List
* Topic Guide
* Comparison
* How-to Guide
* Alternatives Guide
Input:
* Primary keyword or topic
* Target audience
* Desired word count
* Tone and style preferences
* Additional context
Searchable's AI:
* Analyzes top-ranking content
* Reviews competitor approaches
* Identifies content gaps
* Finds citation-worthy sources
* Determines optimal structure
AI creates:
* Optimized headlines and subheadings
* Well-structured body content
* Proper citations and references
* Internal linking suggestions
* Meta titles and descriptions
You can:
* Edit generated content
* Request revisions
* Add images and links
* Adjust tone or depth
* Add brand-specific details
* Verify factual accuracy
Finally:
* Run final SEO/AEO check
* Add structured data
* Publish to your CMS
## Content Types
### Blog Post
**Best for:**
* Thought leadership
* Industry insights
* News and trends
* Opinion pieces
**Optimization includes:**
* Keyword integration
* Internal linking
* Featured snippet targets
* Citation-worthy facts
### Article
**Best for:**
* In-depth topic exploration
* Long-form content
* Research-backed pieces
* Educational resources
**Optimization includes:**
* Comprehensive topic coverage
* Authoritative sources
* Structured sections
* Expert insights
* Schema markup
### Listicle
**Best for:**
* Top 10 lists
* Curated recommendations
* Quick tips
* Resource roundups
**Optimization includes:**
* Numbered structure
* Scannable format
* Engaging headlines
* Visual appeal
* Featured snippet optimization
### How-To Guide
**Best for:**
* Step-by-step tutorials
* Process documentation
* Educational content
* Setup instructions
**Optimization includes:**
* Clear sequential steps
* HowTo schema markup
* Visual aids suggestions
* Time estimates
* Difficulty indicators
### Newsletter
**Best for:**
* Regular updates
* Subscriber engagement
* Curated content
* Company news
**Optimization includes:**
* Engaging subject lines
* Scannable sections
* Clear CTAs
* Personalization elements
* Mobile-friendly format
### Comparison
**Best for:**
* Product vs. product
* Feature comparisons
* Buying guides
* Alternative recommendations
**Optimization includes:**
* Fair, balanced comparisons
* Specification tables
* Pros and cons lists
* Price comparisons
* Decision frameworks
### Review
**Best for:**
* Product evaluations
* Service reviews
* Tool assessments
* Honest recommendations
**Optimization includes:**
* Rating systems
* Review schema markup
* Pros and cons sections
* Use case scenarios
* Expert verdict
## AI Content Features
### Citation Management
All generated content includes:
* Properly cited sources
* Hyperlinked references
* Author credentials where relevant
* Publication dates
* Fact-checking notes
Citations make content more trustworthy for both readers and AI models.
### Structured Data Integration
Automatic schema markup for:
* Article schema
* FAQ schema
* HowTo schema
* Product schema
* Review schema
### SEO Optimization
Every piece includes:
* Target keyword in title and H1
* Optimal keyword density (2-3%)
* LSI keyword integration
* Internal linking suggestions
* Optimized meta descriptions
* Image alt text suggestions
### AEO Optimization
Content is optimized for AI citation:
* Clear, direct answers
* Comprehensive topic coverage
* Logical information hierarchy
* Entity-rich language
* Definition boxes
* Summary sections
## Content Workflows
### Individual Articles
For one-off content needs:
1. Navigate to **Content** → **New Article**
2. Enter topic and parameters
3. Generate outline
4. Review and approve
5. Generate full article
6. Edit and refine
7. Publish
### Content Calendar
Plan content strategically:
* Schedule generation dates
* Coordinate with marketing campaigns
* Track content clusters
* Manage team assignments
* Monitor publishing pipeline
Automated posting requires integration with your website content management platform (CMS).
## Content Quality Standards
Original content (not duplicated)
Fact-checked and cited
Proper grammar and readability
Optimized for target keywords
Includes multimedia suggestions
Mobile-friendly formatting
Passes plagiarism checks
Always review AI-generated content for accuracy, brand voice, and factual correctness before publishing.
## Performance Tracking
Monitor how your content performs:
### SEO Metrics
* Keyword rankings
* Organic traffic
* Backlinks acquired
* Time on page
* Bounce rate
### AEO Metrics
* AI model citations
* Prompt performance
* Brand mentions
* Share of voice
### Engagement Metrics
* Page views
* Social shares
* Comments
* Conversions
Searchable provides you with visibility on majority of key metrics, but it's always good to check your analytics platforms to validate your insights.
## Best Practices
Start with a clear content brief
Review and edit all AI-generated content
Add unique insights and examples
Include original data or research
Update content regularly (quarterly)
Monitor performance and optimize
Build content clusters around topics
## Content Templates
Pre-built templates for common formats:
* **Ultimate Guide Template**: Comprehensive topic coverage
* **Comparison Template**: Product vs. product
* **How-To Template**: Step-by-step instructions
* **Listicle Template**: "Top 10" style articles
* **News Analysis Template**: Industry news commentary
* **Case Study Template**: Customer success stories
## Advanced Features
### Content Refresh
Update existing content:
* Identify outdated articles
* Generate updated sections
* Preserve top-performing elements
* Add new information
* Update statistics and examples
### Multi-Language Support (Custom plan)
Generate content in multiple languages:
* 20+ supported languages
* Native speaker quality
* Cultural adaptation
* Local SEO optimization
### Custom Style Guides (Custom plan)
Train AI on your brand voice:
* Upload style guide documents
* Provide example articles
* Define tone preferences
* Set terminology rules
## Limitations & Considerations
**What AI Content Does Well:**
* Research and information gathering
* Structure and organization
* SEO optimization
* Citation finding
* First drafts
**What Requires Human Touch:**
* Brand voice nuances
* Original insights
* Personal anecdotes
* Controversial opinions
* Final fact-checking
AI content generation is a tool to enhance productivity, not replace human creativity and expertise.
## Pricing & Limits
See detailed pricing and content generation limits for all plans
## Next Steps
Start creating content now
Plan content based on AI demand
Connect your publishing platform
Optimize your content scores
# Site Audits
Source: https://docs.searchable.com/using-searchable/site-audits
Run comprehensive technical and content audits to identify and fix optimization issues
## Overview
Searchable's audit system performs deep analysis of your website to identify technical SEO issues, content quality problems, and AEO optimization opportunities. Get actionable recommendations prioritized by impact.
Performance, speed, and technical SEO
Content quality and optimization
AI readiness and structured data
## Audit Types
### Quick Audit (30 seconds)
Fast scan of critical issues:
* Core Web Vitals check
* Major technical errors
* Critical content gaps
* Priority recommendations
**Best for:**
* Quick health checks
* Pre-launch reviews
* Post-update validation
### Comprehensive Audit (2-10 minutes)
Deep analysis of all pages:
* Full technical SEO audit
* Content quality analysis
* AEO optimization review
* Competitive benchmarking
* Historical comparison
**Best for:**
* Monthly reviews
* Strategy planning
* Identifying opportunities
### Continuous Monitoring
Automated ongoing audits:
* Catch issues immediately
* Track improvement trends
* Alert on regressions
* Flexible audit scheduling
Number of pages monitored continuously varies depending on your plan.
## Running an Audit
Start auditing your site
Go to your project dashboard → **Run Audit** button
Choose quick or comprehensive based on your needs
* All pages or specific URLs
* Include/exclude sections
* Mobile or desktop analysis
Click **"Start Audit"** and wait for completion. Most finish in 2-10 minutes.
See prioritized issues and recommendations
## Understanding Audit Results
### Issue Severity Levels
**Critical (Red)**
* Severe problems impacting site function
* Major SEO penalties
* Broken core functionality
* Security vulnerabilities
**High (Orange)**
* Significant impact on rankings
* Poor user experience
* Major performance issues
* Missing critical content
**Medium (Yellow)**
* Moderate optimization opportunities
* Minor technical issues
* Content improvements needed
* Best practice violations
**Low (Blue)**
* Nice-to-have optimizations
* Minor improvements
* Future-proofing recommendations
* Advanced optimizations
## Common Issues Found
### Technical Issues
* Large image files
* Unoptimized JavaScript
* Render-blocking resources
* Slow server response
* Missing compression
**Fix:** Compress images, minify code, enable caching
* Text too small
* Touch targets too close
* Content wider than screen
* Incompatible plugins
**Fix:** Implement responsive design, test on devices
* 404 pages
* Redirect chains
* Broken internal links
* Blocked resources
* Invalid XML sitemap
**Fix:** Fix links, create redirects, update sitemap
* Mixed content warnings
* Invalid SSL certificate
* HTTP version still accessible
* Insecure resources
**Fix:** Force HTTPS, update resources, renew certificates
### Content Issues
* Pages with less than 300 words
* Duplicate content
* Low-value pages
* Missing key information
**Fix:** Expand content, consolidate duplicates, add value
* No title tags
* Missing meta descriptions
* Duplicate titles/descriptions
* Too long or too short
**Fix:** Add unique, optimized meta data to each page
* Missing H1 tags
* Incorrect heading hierarchy
* No internal links
* Long paragraphs
**Fix:** Implement proper heading structure, add links
* No target keywords
* Keyword cannibalization
* Over-optimization
* Irrelevant keywords
**Fix:** Define clear keyword strategy, consolidate content
### AEO Issues
* No schema markup
* Incomplete schemas
* Invalid JSON-LD
* Missing entities
**Fix:** Implement Article, FAQ, HowTo, and Organization schemas
* No direct answers
* Unclear explanations
* Missing definitions
* Lack of examples
**Fix:** Add clear answers, definitions, and examples
* No author bios
* Missing sources
* Outdated content
* No expertise signals
**Fix:** Add author credentials, cite sources, update content
## Issue Prioritization
Searchable automatically prioritizes fixes by:
1. **Impact Score**: How much it affects your scores
2. **Effort Level**: Easy, medium, or hard to fix
3. **Page Importance**: Based on traffic and conversions
4. **Issue Frequency**: How many pages are affected
### Quick Wins
Filter for high-impact, low-effort fixes:
* Missing alt text
* Broken internal links
* Missing meta descriptions
* Duplicate content
* Image optimization
**Expected improvement:** 5-15 points in affected scores
### Long-Term Projects
High-impact but time-intensive:
* Site-wide redesign
* Content rewrite projects
* Technical infrastructure changes
* Structured data implementation
**Expected improvement:** 20-40 points over 3-6 months
## Taking Action on Issues
### For Each Issue
**View Details:**
* Issue description
* Why it matters
* Affected pages
* How to fix
* Code examples
* Expected impact
**Actions:**
* Mark as "In Progress"
* Assign to team member
* Add notes
* Set deadline
* Mark as "Resolved"
### Bulk Actions
For issues affecting multiple pages:
* Export affected URLs
* Apply fixes in bulk
* Track progress
* Re-audit to verify
## Re-Auditing After Fixes
Implement recommendations from audit
Allow 24-48 hours for changes to propagate
Compare before and after results
Check that scores increased and issues resolved
## Best Practices
Run audits after any major site changes
Fix critical issues immediately
Tackle high-impact quick wins first
Set aside time monthly for audits
Track progress with historical comparison
Re-audit after implementing fixes
Monitor automated audits for regressions
## Integration Benefits
### With Google Search Console
* Correlate audit findings with search data
* Prioritize based on traffic impact
* Track keyword-specific improvements
### With Google Analytics
* Identify high-traffic pages needing fixes
* Measure conversion impact
* Prioritize by business value
### With CMS
* Direct fix implementation
* Content update workflows
* Publishing optimization
## Common Questions
* Quick audit: 30-60 seconds
* Comprehensive audit: 2-10 minutes
* Time varies based on site size and complexity
No. Searchable's crawler is rate-limited and respects your server resources. We won't impact your site's performance for real users.
You can audit any public website, but detailed tracking features require domain verification on Professional, Agency, or Custom plans.
* After site changes: Immediately
* Regular monitoring: Weekly (Starter) or Daily (Professional+)
* Strategic reviews: Monthly comprehensive audits
This feature is coming soon. If you'd like to know more, reach out to us on [Community Slack](https://join.slack.com/t/searchablecommunity/shared_invite/zt-3d72toig3-5CNPzd1ujFQu_IanWGTHDA).
## Next Steps
Start auditing your site now
Learn what affects your scores
Detailed fix instructions
Common audit problems
# Troubleshooting
Source: https://docs.searchable.com/using-searchable/troubleshooting
Solutions to common issues and problems in Searchable
## Common Issues
Quick solutions to the most frequent problems users encounter.
### Problem
Your prompts show 0% mention rate and AI models never cite your brand.
### Causes
* Brand is too new or unknown
* No comprehensive content about your products/services
* Missing structured data and schema markup
* Low domain authority
### Solutions
Write comprehensive articles about:
* What your product/service is
* How it works
* Key features and benefits
* Use cases and examples
Add schema markup:
* Organization schema with logo and description
* Product/Service schemas
* FAQ schema
* Article schema on blog posts
* Get mentioned in industry publications
* Earn backlinks from authoritative sites
* Create original research and data
* Establish thought leadership
Begin with brand-specific prompts like:
* "What is \[Your Brand]?"
* "Tell me about \[Your Company]"
Then expand to category queries.
AI model training updates take time. Allow 4-8 weeks for improvements to show in visibility tracking.
If you have zero mentions after 3 months of optimization, contact support for a strategy review.
### Problem
Audits get stuck or time out without completing.
### Causes
* Large site with many pages
* Slow server response times
* Robots.txt blocking Searchable's crawler
* Firewall or security blocking our IP addresses
### Solutions
Ensure Searchable's user agent is allowed:
```text theme={null}
User-agent: SearchableBot
Allow: /
```
* Check your server response times
* Ensure your site isn't down or overloaded
* Contact your hosting provider if needed
* Limit audit to fewer pages
* Start with your most important pages
* Gradually expand scope
If you have firewall rules, whitelist our crawler IPs (available in Settings → Security)
If issues persist after these steps, contact support with:
* Your project ID
* The timestamp of failed audits
* Any error messages
### Problem
Unable to connect Google Search Console, Google Analytics, or CMS integrations.
### Solutions by Integration
**Google Search Console:**
* Ensure you have Owner or Full User permission in GSC
* Verify the property is verified in GSC
* Use the same Google account for both GSC and Searchable
* Try disconnecting and reconnecting
* Clear browser cache and cookies
**Google Analytics 4:**
* Confirm you have at least Editor access to the GA4 property
* Ensure GA4 property is active (not archived)
* Check that data is flowing into GA4
* Verify you're selecting the correct property/stream
Most integration issues are resolved by disconnecting, clearing cache, and reconnecting with fresh credentials.
### Problem
Your scores decreased significantly without any changes on your end.
### Possible Causes
* Competitors improved (relative scoring)
* New technical issues detected
* Third-party scripts causing slowdowns
* Server performance degradation
* Algorithm updates in scoring model
### Investigation Steps
Review any recent updates to:
* Your website
* Hosting environment
* Third-party integrations
* Content changes
Go to Issues tab and look for:
* New critical or high-priority issues
* Recently detected problems
* Issues affecting multiple pages
Use audit history to compare:
* Before and after scores
* New issues that appeared
* Changes in specific metrics
* Run PageSpeed Insights
* Check Core Web Vitals
* Test server response time
* Monitor uptime
If you track competitors, check if they improved significantly
### Problem
Some of your pages aren't showing up in the monitored pages list.
### Causes
* Pages not linked from homepage
* Blocked by robots.txt or noindex
* Sitemap is not available or not up to date
* Behind authentication
* JavaScript-rendered content
* Crawl depth limit reached
### Solutions
Ensure pages are linked from your homepage or sitemap within 3 clicks
Check that pages:
* Don't have noindex tags
* Aren't blocked in robots.txt
* Return 200 status codes
* Don't require login
Go to Pages → Add Page and enter specific URLs you want to monitor
In Settings → Crawl Configuration:
* Increase crawl depth
* Adjust included/excluded patterns
* Enable JavaScript rendering if needed
* Ensure you have an XML sitemap
* Submit it in project settings
* Verify sitemap is accessible
### Problem
Dashboard takes a long time to load or feels sluggish.
### Quick Fixes
* **Reduce date range**: Shorter time periods load faster
* **Limit pages**: Monitor fewer pages
* **Clear filters**: Reset any active filters
* **Clear browser cache**: Force refresh (Ctrl+F5 or Cmd+Shift+R)
* **Use modern browser**: Chrome, Firefox, or Edge latest versions
* **Check internet connection**: Ensure stable, fast connection
### If Problems Persist
* Try incognito/private mode
* Disable browser extensions
* Check browser console for errors (F12)
* Contact support with browser and network details
### Problem
Getting 429 (Too Many Requests) or other API errors.
### Solutions
**Plan availability:** API keys are included with Custom contracts. Starter, Professional, and Agency accounts rely on in-platform workflows and cannot generate API keys.
**If you have Custom access:**
1. Go to Settings → API to confirm credentials and observe usage
2. Review which endpoints are consuming quota and adjust batching or caching
3. Reach out to your success manager for temporary limit increases when needed
**Reduce Usage:**
* Implement caching on your end
* Batch requests where possible
* Optimize polling frequency
**API Error Codes:**
* 401: Invalid or expired API key
* 403: Insufficient permissions
* 404: Resource not found
* 429: Rate limit exceeded
* 500: Server error (contact support)
```bash Example: Check API Status theme={null}
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://api.searchable.com/v1/status
```
### Problem
Payment failed, subscription cancelled, or billing questions.
### Common Issues
**Payment Failed:**
* Update payment method in Settings → Billing
* Check card hasn't expired
* Verify sufficient funds
* Contact bank if card is being declined
**Subscription Not Active:**
* Check email for failed payment notices
* Verify billing cycle and renewal date
* Contact support if charged but not upgraded
**Upgrade Not Applied:**
* Upgrades are immediate
* Try logging out and back in
* Clear browser cache
* Check confirmation email
**Downgrade Questions:**
* Downgrades apply at end of billing period
* Data preserved for 30 days
* Can re-upgrade anytime
**Refunds:**
* Contact support within 14 days
* Must not have exceeded usage limits
* One-time courtesy refunds available
### Problem
Team members can't access project or see incorrect data.
### Solutions
**Member Can't See Project:**
* Verify invitation was sent and accepted
* Check email spam folder for invitation
* Resend invitation from Settings → Team
* Ensure correct email address was used
**Wrong Permissions:**
* Review role assignments (Admin, Editor, Viewer)
* Update roles in Settings → Team → Manage
* Remember: changes take effect immediately
**SSO Issues (Custom):**
* Verify SSO is configured correctly
* Check user is in correct organization
* Test with different user
* Review audit logs
Team features are available on Professional, Agency, and Custom plans only.
## Getting Additional Help
### Support Resources
Browse all documentation
[support@searchable.com](mailto:support@searchable.com)
Ask the community
Check system status
### Response Times
* **Starter**: Email support, 2-3 business days
* **Professional**: Priority support, 24-hour response
* **Agency**: Dedicated success manager with same-business-day replies
* **Custom**: SLA-backed support with contracted response times
### When Contacting Support
Include these details for faster resolution:
Project ID (found in Settings)
What you were trying to do
Steps to reproduce the problem
Screenshots or error messages
Browser and OS version
When the problem started
## Feature Requests
Have an idea for improving Searchable?
1. **Check Existing Requests**: Visit our [Feature Request Board](https://features.searchable.com)
2. **Vote on Requests**: Upvote features you want
3. **Submit New Ideas**: Create new feature requests
4. **Track Progress**: See what's in development
Popular requests get prioritized!
## Report a Bug
Found a bug?
1. Go to Settings → Help → Report Bug
2. Describe the bug in detail
3. Include steps to reproduce
4. Attach screenshots if helpful
5. Note your environment (browser, OS, plan)
We aim to fix critical bugs within 24-48 hours.
## Emergency Support
For critical production issues affecting your business:
**Custom Customers:**
* Use the emergency line provided in your onboarding packet
* Direct access to engineering with 1-hour SLA
**Agency Customers:**
* Mark support tickets as "Urgent"
* Dedicated manager responds within the same business day
**Professional Customers:**
* Flag tickets as high priority for fastest routing
* Expect responses within 24 hours on business days
**Starter & Trial Users:**
* Join our Slack community for the quickest peer assistance
* Critical security issues are escalated immediately
## Next Steps
Still having issues?
Get personalized help
Ask the community
# Understanding Scores
Source: https://docs.searchable.com/using-searchable/understanding-scores
Learn how Searchable calculates and interprets your optimization scores
Ask your Searchable Agent for help if you want to understand or dig deeper into any of your scores.
## Score Overview
Searchable uses a comprehensive scoring system (0-100) to measure your site's optimization across multiple dimensions. Each score provides actionable insights into specific aspects of your online presence.
Site performance, speed, and technical SEO
Content quality, structure, and optimization
Answer Engine Optimization readiness
Combined weighted score
## Technical Score (0-100)
### What It Measures
Your Technical Score evaluates the technical foundation of your website that affects both traditional search engines and AI crawlers.
### Components & Weighting
**Page Speed (30%)**
* First Contentful Paint (FCP)
* Largest Contentful Paint (LCP)
* Time to Interactive (TTI)
* Total Blocking Time (TBT)
**Mobile Optimization (25%)**
* Mobile-friendliness
* Responsive design
* Touch target sizing
* Viewport configuration
**Core Web Vitals (20%)**
* LCP (Largest Contentful Paint)
* FID (First Input Delay)
* CLS (Cumulative Layout Shift)
**Technical SEO (15%)**
* XML sitemap presence and validity
* Robots.txt configuration
* Canonical tags
* HTTPS implementation
* Structured data
**Crawlability (10%)**
* Internal linking structure
* Broken links
* Redirect chains
* URL structure
* Server response codes
### Score Interpretation
| Score Range | Status | What It Means |
| ----------- | --------- | ---------------------------------------------------------------- |
| 90-100 | Excellent | Technical foundation is solid. Minor optimizations only. |
| 70-89 | Good | Generally well-optimized with some room for improvement. |
| 50-69 | Fair | Several technical issues affecting performance and crawlability. |
| 30-49 | Poor | Significant technical problems that need immediate attention. |
| 0-29 | Critical | Major technical issues severely impacting site performance. |
### How to Improve
**Quick Wins:**
* Compress and optimize images
* Enable browser caching
* Minify CSS, JavaScript, and HTML
* Use a CDN for static assets
* Reduce server response time
**Advanced:**
* Implement lazy loading for images
* Use modern image formats (WebP, AVIF)
* Defer non-critical JavaScript
* Optimize web fonts
**Quick Wins:**
* Test on multiple mobile devices
* Ensure text is readable without zooming
* Make buttons and links touch-friendly (min 48px)
* Avoid intrusive popups
**Advanced:**
* Implement responsive images
* Optimize for different screen sizes
* Test on slow network conditions
**For LCP (\< 2.5s):**
* Optimize largest element loading
* Preload important resources
* Reduce server response time
**For FID (\< 100ms):**
* Minimize JavaScript execution
* Break up long tasks
* Use web workers for heavy computations
**For CLS (\< 0.1):**
* Set size attributes for images/videos
* Reserve space for ads
* Avoid inserting content above existing content
**Quick Wins:**
* Create and submit XML sitemap
* Implement canonical tags
* Add structured data (Schema.org)
* Fix broken links
**Advanced:**
* Optimize crawl budget
* Implement hreflang for international sites
* Use semantic HTML5 elements
* Optimize URL structure
Use the Issues tab to see specific technical problems. Searchable prioritizes fixes by impact.
## Content Score (0-100)
### What It Measures
Your Content Score evaluates the quality, structure, and optimization of your content for both readers and AI models.
### Components & Weighting
**Content Quality (30%)**
* Depth and comprehensiveness
* Original, valuable information
* Clear, well-written text
* Proper grammar and spelling
* Content-to-code ratio
**Keyword Optimization (25%)**
* Target keyword usage
* Keyword density (not overstuffed)
* LSI keywords and semantic relevance
* Keyword placement (title, headings, first paragraph)
**Content Structure (20%)**
* Proper heading hierarchy (H1, H2, H3)
* Paragraph length and readability
* List and table usage
* Content organization
* Table of contents for long content
**Internal Linking (15%)**
* Internal links quantity
* Relevant anchor text
* Link depth from homepage
* Topical clustering
**Meta Data (10%)**
* Title tag optimization
* Meta description quality
* Header tags (H1-H6)
* Image alt text
* Open Graph tags
### Score Interpretation
| Score Range | Status | What It Means |
| ----------- | --------- | -------------------------------------------------------------- |
| 90-100 | Excellent | Content is comprehensive, well-optimized, and highly valuable. |
| 70-89 | Good | Quality content with minor optimization opportunities. |
| 50-69 | Fair | Content needs improvement in structure or depth. |
| 30-49 | Poor | Thin or poorly optimized content requiring significant work. |
| 0-29 | Critical | Very thin or missing content. Major rewrite needed. |
### How to Improve
**Quick Wins:**
* Add more detailed explanations
* Include examples and case studies
* Update outdated information
* Add visual elements (images, videos)
* Improve readability (shorter sentences, clear language)
**Advanced:**
* Conduct original research
* Interview industry experts
* Create comprehensive guides
* Add unique data and statistics
**Quick Wins:**
* Include target keyword in title
* Use keyword in first 100 words
* Add keyword to at least one H2
* Use natural variations throughout
**Advanced:**
* Research and use LSI keywords
* Target long-tail variations
* Analyze top-ranking content
* Avoid keyword stuffing (2-3% density max)
**Quick Wins:**
* Use clear heading hierarchy
* Break long paragraphs (3-4 sentences max)
* Add bullet points and numbered lists
* Include a table of contents for long articles
**Advanced:**
* Create content clusters around topics
* Use jump links for navigation
* Implement FAQ sections
* Add summary boxes
**Quick Wins:**
* Link to relevant related content
* Use descriptive anchor text
* Add 3-5 internal links per page
* Fix broken internal links
**Advanced:**
* Create topic clusters with pillar pages
* Implement breadcrumbs
* Build a hub-and-spoke structure
* Use contextual linking
## AEO Score (0-100)
### What It Measures
Answer Engine Optimization (AEO) Score evaluates how well your content is optimized for AI-powered search engines and language models like ChatGPT, Claude, and Perplexity.
AEO is the evolution of SEO for the AI era. It focuses on making your content easily understood and cited by AI models.
### Components & Weighting
**Structured Data (25%)**
* Schema.org markup implementation
* Rich snippets optimization
* Knowledge graph eligibility
* Entity markup
**Answer Format (25%)**
* Clear, direct answers to questions
* Featured snippet optimization
* FAQ sections
* How-to formats
**Citation Worthiness (20%)**
* Authoritative content
* Proper sourcing and citations
* Expert author bios
* Trustworthy references
**Semantic Richness (20%)**
* Entity recognition
* Topic depth and breadth
* Related concepts coverage
* Context clarity
**AI Accessibility (10%)**
* Clean HTML structure
* Logical content flow
* No excessive advertising
* Fast loading
### Score Interpretation
| Score Range | Status | What It Means |
| ----------- | --------- | ------------------------------------------------------------------ |
| 90-100 | Excellent | Highly optimized for AI engines. Likely to be cited frequently. |
| 70-89 | Good | Well-formatted for AI with some optimization opportunities. |
| 50-69 | Fair | Basic AI compatibility. Needs structured data and clearer answers. |
| 30-49 | Poor | Difficult for AI to parse. Missing key AEO elements. |
| 0-29 | Critical | Not AI-friendly. Major restructuring needed. |
### How to Improve
**Quick Wins:**
* Add Organization schema
* Implement Article schema
* Add FAQ schema for Q\&A content
* Include Product schema for e-commerce
**Advanced:**
* Add HowTo schema for guides
* Implement Review schema
* Use Event schema for events
* Add LocalBusiness schema
```json Example: Article Schema theme={null}
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Your Article Title",
"author": {
"@type": "Person",
"name": "Author Name"
},
"datePublished": "2025-01-15",
"image": "https://example.com/image.jpg",
"publisher": {
"@type": "Organization",
"name": "Your Company",
"logo": {
"@type": "ImageObject",
"url": "https://example.com/logo.png"
}
}
}
```
**Quick Wins:**
* Start with clear, concise answers
* Use question-based headings
* Create FAQ sections
* Format lists and steps clearly
**Advanced:**
* Target featured snippet formats
* Create comprehensive Q\&A content
* Use definition lists for terminology
* Add summary boxes at the top
**Quick Wins:**
* Add author bios with credentials
* Cite reputable sources
* Link to original research
* Update content regularly
**Advanced:**
* Publish original research
* Get cited by authoritative sites
* Build topic authority
* Demonstrate E-E-A-T (Experience, Expertise, Authoritativeness, Trust)
**Quick Wins:**
* Cover related subtopics comprehensively
* Use entity-rich language
* Define technical terms
* Create glossaries
**Advanced:**
* Build comprehensive topic clusters
* Answer related questions
* Cover the full topic ecosystem
* Use natural language variations
## Overall Health Score
### Calculation
Your Overall Health Score is a weighted average of all component scores:
```
Overall Health = (Technical × 0.30) + (Content × 0.35) + (AEO × 0.35)
```
### Why These Weights?
* **Technical (30%)**: Foundation must be solid, but not everything
* **Content (35%)**: Slightly higher weight as it's what users and AI consume
* **AEO (35%)**: Critical for AI visibility in the modern search landscape
### Tracking Progress
**View historical trends:**
* Track scores over time (all plans)
* Data retention: Starter (3 months), Professional (12 months), Agency & Custom (unlimited)
* Compare time periods
* Track after making changes
* Export historical data
**Best Practices:**
* Check scores after each site update
* Monitor trends over weeks, not days
* Focus on improving weakest score first
* Aim for balanced improvement across all scores
## Score Factors Not Included
Searchable scores focus on controllable, measurable factors. We intentionally exclude:
* Domain age and history
* Raw traffic numbers
* Social media engagement
* Backlink quantity (only quality and relevance)
These factors matter for SEO but are either uncontrollable or beyond the scope of content optimization.
## Frequently Asked Questions
Scores update after each audit completes. All plans include continuous monitoring:
* **Starter**: Scores update as audits run within your monthly allocation (25 pages)
* **Professional**: Higher audit capacity (100 pages) for more frequent updates
* **Agency**: 500-page allocation with dedicated success monitoring
* **Custom**: Tailored allocations with SLA-backed updates
Set audit frequency in your project settings based on your needs and plan limits.
Possible reasons:
* Competitor improvements (relative scoring)
* New technical issues discovered
* Algorithm updates in our scoring model
* Server performance degradation
* Third-party script issues
* New pages with poor performance are added to the website
Yes! Many improvements help multiple scores:
* Adding structured data helps both Content and AEO
* Improving page speed helps Technical and user experience
* Better content helps Content, AEO, and engagement
Focus on issues that impact multiple scores first.
* **Technical**: 85+ is achievable for most sites
* **Content**: 80+ with quality content and optimization
* **AEO**: 75+ once structured data is implemented
* **Overall**: 80+ is excellent, 90+ is elite
Focus on consistent improvement rather than perfection.
Higher scores generally mean better AI visibility, but it's not 1:1. Other factors include:
* Brand recognition
* Content topic relevance
* Citation network
* User engagement
Scores provide a strong foundation, but prompt strategy matters too.
## Next Steps
See specific problems affecting your scores
Improve AI visibility beyond technical scores
Generate fresh scores for your site
Connect tools for deeper insights
# AI Visibility Tracking
Source: https://docs.searchable.com/using-searchable/visibility-tracking
Monitor and analyze your brand mentions across AI platforms
## Overview
Track how often and where your brand appears in AI model responses across 9 AI platforms. Visibility tracking helps you understand your AI presence and measure the impact of your content optimization efforts.
Track frequency of brand citations
Your mentions vs. competitors
Where you appear in AI responses
## AI Platforms Monitored
Searchable tracks brand visibility across **9 AI platforms**:
* **ChatGPT** (OpenAI): Most widely used consumer AI
* **Google AI Overviews**: AI-generated summaries in Google Search results
* **Google AI Mode**: Google's AI-powered search experience
* **Gemini**: Google's direct chat interface
* **Perplexity**: AI-powered search and discovery
* **Microsoft Copilot**: AI assistant across Windows, Edge, and Microsoft 365
* **Grok** (xAI): Real-time information access
* **DeepSeek**: Advanced reasoning capabilities
* **Claude** (Anthropic): Popular in enterprise — available on custom plans
Platform availability varies by plan — see [Plans & Pricing](/getting-started/plans-pricing) for which platforms your tier includes.
## Key Metrics
### Visibility Score (0-100)
Measures how prominently your brand appears when AI models mention you.
**Calculation factors:**
* Mention frequency
* Position in responses
* Context quality
* Sentiment
### Presence Rate (0-100%)
Percentage of tracked prompts that mention your brand at all.
**Example:**
* 50 prompts tracked
* Brand mentioned in 15 responses
* Presence Rate: 30%
### Share of Voice
Your brand mentions as a percentage of total category mentions.
**Competitive benchmarking:**
* Compare against industry leaders
* Track trends over time
* Identify gaps and opportunities
## Visibility Reports
### Daily Reports
* Real-time mention tracking
* Platform-by-platform breakdown
* Prompt performance analysis
* Trend indicators
### Weekly Summaries
* Week-over-week changes
* Top performing prompts
* New citations discovered
* Competitive insights
### Monthly Analysis
* Long-term trends
* Campaign impact measurement
* Content correlation
* Strategic recommendations
## Interpreting Your Results
### Strong Visibility (70-100)
Your brand is frequently cited with good positioning.
**Next steps:**
* Maintain current content quality
* Expand to adjacent topics
* Track competitor movements
### Moderate Visibility (40-69)
You're getting some mentions but inconsistently.
**Next steps:**
* Create more comprehensive content
* Optimize for specific prompts
* Improve citation authority
### Low Visibility (0-39)
Your brand is rarely or never mentioned.
**Next steps:**
* Build foundational content
* Focus on brand awareness
* Create citation-worthy resources
## Competitor Tracking
Compare your visibility against competitors:
* Add competitors in Knowledge Base → Competitors
* See side-by-side mention rates
* Identify where competitors outperform
* Discover gaps in your strategy
* Find unoccupied niches you can own
## Source Domains Analysis
Track which domains drive AI visibility:
* Continuous tracking on all plans
* Historical data retention: Starter (3 months), Professional (12 months), Agency & Custom (unlimited)
* Annotation for content updates
* Export data for external analysis
## Platform-Specific Insights
Different AI platforms have different behaviors:
**ChatGPT:**
* Most conservative with citations
* Values authoritative sources
* Updated frequently with new training
**Claude:**
* Detailed, thoughtful responses
* Good at explaining reasoning
* Values comprehensive content
**Gemini:**
* Strong Google integration
* Favors recent content
* Good for real-time queries
**Perplexity:**
* Always provides cited sources
* Real-time web search integration
* Conversational follow-up questions
**Grok:**
* Access to real-time data
* More conversational tone
* Good for current events
## Taking Action on Insights
### For Zero-Mention Prompts
1. Create comprehensive content targeting that prompt
2. Ensure proper structured data
3. Build citation authority
4. Wait 2-4 weeks for AI model updates
### For Low-Ranking Mentions
1. Improve content depth and quality
2. Add more specific examples
3. Include expert insights
4. Build authoritative backlinks
### For High Performers
1. Create similar content for related prompts
2. Expand on successful topics
3. Update regularly to maintain position
## Advanced Features
### Citation Analysis
Understand not just mentions but context:
* Sentiment of mentions (positive/neutral/negative)
* Context in which you're cited
* Specific features or benefits highlighted
* Customer pain points addressed
### Prompt Performance Matrix
Visualize all prompts at once:
* X-axis: Mention rate
* Y-axis: Average position
* Size: Search volume estimate
* Color: Category or priority
## Integration Benefits
### With Google Analytics
* Correlate AI visibility with traffic
* Measure AI-referred conversions
* Identify high-value prompts
### With Google Search Console
* Compare traditional SEO with AEO
* Find synergies between channels
* Unified keyword strategy
## Reporting & Exports
**Available Reports:**
* Visibility summary (PDF)
* Prompt performance (CSV)
* Competitive analysis (PDF)
* Custom reports (Custom plan)
**Scheduling:**
* Daily email summaries
* Weekly team reports
* Monthly executive briefings
## Best Practices
Check visibility weekly, not daily
Focus on trends, not individual data points
Compare periods with similar content updates
Track competitors consistently
Correlate changes with content updates
Set realistic improvement targets (5-10% monthly)
## Common Questions
* New content: 2-4 weeks for AI model updates
* Content improvements: 1-2 weeks
* Brand authority: 3-6 months
AI models update regularly but not instantly.
Each AI platform has: - Different training data cutoff dates - Unique algorithms and preferences -
Varying update frequencies - Different use cases and users
Not significantly. AI visibility requires:
* Quality content for models to reference
* Authoritative sources citing you
* Structured, accessible information
Technical optimization helps, but content is king.
## Next Steps
Create better prompts for tracking
Generate AI-optimized content
Improve your technical foundation
Run comprehensive site audits
# Working with Prompts
Source: https://docs.searchable.com/using-searchable/working-with-prompts
Master the art of creating and managing prompts to track your AI visibility
## What Are Prompts?
Prompts are questions or queries that you want to track across AI platforms. Think of them as the "keywords" of AI search - they help you understand when and how AI models mention your brand.
While Search Engines like Google operate primarily on short phrases, or "keywords", AI search is much more conversational in nature. While you may search for 'best running sneakers' on Google, AI search will provide better answers for queries such as 'best road running sneakers on a budget, ideally waterproof'.
## Why Prompts Matter
### The AI Search Shift
Users are increasingly asking AI assistants for recommendations:
* "What's the best CRM for small businesses?"
* "How do I optimize my website for SEO?"
* "How can I introduce more colours to my decor?"
If your brand isn't mentioned in these AI responses, you're invisible to potential customers.
### What We Track
Searchable monitors your prompts across major AI platforms:
ChatGPT
Claude (Opus, Sonnet, Haiku)
Gemini (Pro, Ultra)
Perplexity AI
xAI Grok, DeepSeek, Meta Llama
## Creating Effective Prompts
### Prompt Anatomy
A great prompt has three components:
1. **Context**: Who is asking and what's their situation?
2. **Intent**: What information are they seeking?
3. **Specificity**: Enough detail to generate useful responses
### Good vs. Bad Prompts
```text Bad Prompt theme={null}
CRM software
```
```text Good Prompt theme={null}
What are the best CRM software options for a small business with 10-20 employees that integrates with email marketing?
```
**Why the difference?**
* Bad: Too vague, will generate generic lists
* Good: Specific context, clear intent, qualified criteria
Reusing your SEO keywords as prompts is not a good AEO strategy.
### Prompt Templates by Industry
**Product Comparison**
```text theme={null}
What are the best [your category] tools for [target audience]
who need [key feature]?
```
**Problem-Solution**
```text theme={null}
How can [target audience] solve [specific problem]
without [common pain point]?
```
**Feature Inquiry**
```text theme={null}
Which [product category] offers [specific feature]
and integrates with [popular tool]?
```
**Product Recommendations**
```text theme={null}
What's the best [product type] for [use case]
under [price range]?
```
**Buying Guides**
```text theme={null}
What should I look for when buying [product category]
for [specific need]?
```
**Alternative Seeking**
```text theme={null}
What are good alternatives to [competitor]
that are [better/cheaper/more feature-rich]?
```
**Service Provider Selection**
```text theme={null}
How do I choose the right [service type] for [specific situation]?
```
**Local Queries**
```text theme={null}
Who are the top [service providers] in [location]
for [specific service]?
```
**Qualification Questions**
```text theme={null}
What questions should I ask when hiring a [service professional]?
```
**Resource Discovery**
```text theme={null}
What are the best resources for learning [topic]
at [skill level]?
```
**Content Recommendations**
```text theme={null}
Can you recommend [content type] about [topic]
that covers [specific aspect]?
```
**Comparison Content**
```text theme={null}
What's the difference between [concept A] and [concept B]
in [context]?
```
## Prompt Strategy
### The Prompt Pyramid
Build your prompt library strategically:
Direct mentions of your brand name
**Examples:**
* "What is \[Your Brand]?"
* "Tell me about \[Your Company]"
* "How does \[Your Product] work?"
**Purpose**: Establish baseline brand awareness
Your product/service category without brand name
**Examples:**
* "What are the best \[category] for \[audience]?"
* "How do I choose a \[category]?"
* "What features should I look for in \[category]?"
**Purpose**: Compete for category dominance
Problems your product solves, without mentioning solutions
**Examples:**
* "How can I \[achieve goal]?"
* "What's the best way to \[solve problem]?"
* "I'm struggling with \[pain point], what should I do?"
**Purpose**: Capture users before they know solutions exist
Related topics where your brand adds value
**Examples:**
* "What is \[related concept]?"
* "How do \[adjacent process] work?"
* "Best practices for \[related activity]?"
**Purpose**: Build topic authority beyond your core offering
### Prompt Diversity
Balance your prompts across dimensions:
| Dimension | Why It Matters | Example Balance |
| ----------------------- | ---------------------------------------------------------------- | ---------------------------------------------- |
| **Specificity** | Broad prompts show awareness, specific ones show purchase intent | 40% broad, 60% specific |
| **Buying Stage** | Track the full customer journey | 30% awareness, 40% consideration, 30% decision |
| **Competitor Mentions** | Understand your competitive position | 20% include competitor names |
| **Question Types** | Different formats appeal to different users | Mix "what", "how", "why", "which" |
## Managing Your Prompt Library
### In the Searchable Dashboard
**Actions Available:**
* Create new prompts
* Edit existing prompts
* Archive low-performing prompts
* Bulk import/export
* Analyze performance
* View mention history
### Creating a Prompt
Go to **Prompts** tab in your project
Click the **"+ New Prompt"** button
Type your prompt exactly as a user would ask it
Test your prompt in ChatGPT or another AI platform first to see what kinds of responses it generates.
* **Category**: Organize prompts by type
* **Priority**: Mark important prompts
* **Tags**: Add labels for filtering
Click **"Save & Run"** to immediately test across all AI platforms
Initial results appear within 30-60 seconds. Historical tracking begins immediately.
### Bulk Import
For adding many prompts at once:
1. **Download Template**
* Go to Prompts → **Import**
* Download the CSV template
2. **Fill Template**
* One prompt per row
* Include category and tags columns
* Maximum 1000 prompts per import
```csv Example: prompts-import.csv theme={null}
prompt,category,tags,priority
"What are the best CRM tools for startups?",Product Comparison,"crm,startup,comparison",High
"How do I automate my email marketing?",Problem Solution,"email,automation,how-to",Medium
"What is [Your Brand]?",Brand Query,"brand,awareness",High
```
3. **Upload & Review**
* Upload your CSV file
* Review detected prompts
* Fix any errors
* Click **"Import All"**
### Prompt Templates
Save time with pre-built templates:
**Access Templates:**
* Go to Prompts → **Templates**
* Browse by industry or use case
* Click **"Use Template"**
* Customize for your brand
**Available Template Categories:**
* SaaS Product Queries
* E-commerce Product Recommendations
* Service Provider Selection
* Content Discovery
* Local Business Queries
* B2B Software Evaluation
## Analyzing Prompt Performance
### Key Metrics
How often your brand appears in responses
Where you rank when mentioned (1-10)
Your mentions vs. total category mentions
Positive, neutral, or negative mentions
### Interpreting Results
**High Performers (80%+ mention rate)**
* Great! These prompts consistently mention your brand
* Action: Create similar prompts to expand this success
**Medium Performers (30-79% mention rate)**
* Promising opportunities for improvement
* Action: Optimize content to better match these prompts
**Low Performers (below 30% mention rate)**
* Either too competitive or need better content alignment
* Action: Create targeted content or refine prompt wording
**Zero Mentions**
* Not necessarily bad - could be opportunity queries
* Action: Create comprehensive content specifically for these prompts
### Prompt Optimization Cycle
Let prompts collect data across multiple AI platforms
Identify which prompts generate mentions and which don't
Write articles targeting zero-mention prompts
Improve pages that get partial mentions to increase frequency
Create new prompts based on what's working
Continuous optimization is key to AI visibility
## Advanced Prompt Techniques
### Competitor Tracking
Include competitors in your prompts to understand your position:
**Comparison Prompts:**
```text theme={null}
What's better: [Your Brand] or [Competitor]?
Compare [Your Brand] vs [Competitor] for [use case]
[Your Brand] alternatives that are [better criterion]
```
**Market Landscape:**
```text theme={null}
What are the top 5 [category] tools?
Who are the leaders in [industry]?
What are the best [category] companies?
```
### Sentiment Analysis
Track not just mentions, but how you're mentioned:
* Monitor positive vs. negative sentiment
* Identify common criticisms
* Track feature-specific sentiment
* Compare sentiment to competitors
### Time-Based Prompts
Some prompts are seasonal or time-sensitive:
**Examples:**
```text theme={null}
Best [product] for 2025
Top [category] tools this year
Latest trends in [industry]
```
**Strategy:**
* Create year-specific prompts
* Update annually
* Archive outdated versions
### Local Prompts
For location-based businesses:
**Examples:**
```text theme={null}
Best [service] in [city]
Top [business type] near [location]
Where to find [product] in [area]
```
## Prompt Best Practices
Start with 10-20 prompts and expand gradually
Test prompts in ChatGPT before adding to Searchable
Focus on questions your customers actually ask
Include competitor names strategically
Update prompts quarterly to stay current
Archive low-performing prompts after 3 months
Create content specifically targeting zero-mention prompts
Avoid "gaming" the system by creating prompts that are too specific to your brand. Focus on genuine user queries for meaningful insights.
## Industry-Specific Strategies
### SaaS
* Focus heavily on feature comparison prompts
* Track integration-related queries
* Monitor pricing and plan comparisons
* Include use-case specific prompts
### E-commerce
* Product recommendation prompts
* Price-point specific queries
* Alternative and comparison prompts
* Seasonal buying queries
### Services
* Problem-solution prompts
* Qualification and vetting questions
* Local service queries
* Industry-specific how-to prompts
### Content/Publishing
* Resource discovery prompts
* Learning and education queries
* "Best of" list prompts
* Tutorial and guide requests
## Frequently Asked Questions
* Start with 10-20 prompts and expand based on performance
* Most businesses find 50-200 prompts sufficient for comprehensive coverage
* Quality matters more than quantity - focus on prompts your customers actually ask
* **Add new prompts**: Monthly
* **Review performance**: Weekly
* **Update existing prompts**: Quarterly
* **Archive low performers**: Every 3 months
Prompt strategy should evolve with your business and market.
Yes! Overly specific prompts (e.g., "Tell me everything about \[Your Brand]'s exact feature set") won't reflect real user queries. Balance specificity with natural language.
Common reasons:
* Your brand isn't well-known enough yet
* No content specifically answers that prompt
* The prompt is too competitive
* AI models lack training data about your brand
**Solution**: Create comprehensive content targeting those prompts and build brand authority.
Yes, strategically! Including competitors helps you:
* Understand your competitive position
* Identify where you're being compared
* Find alternative-seeking queries
Aim for 20-30% of prompts to include competitor names.
Custom plans support multi-language prompts. Contact sales for:
* Language-specific prompt libraries
* Region-specific AI model tracking
* International brand visibility monitoring
## Prompt Library Resources
Industry-specific prompt templates
AI-powered prompt suggestions
Connect with other users and share prompts
## Next Steps
Create your first prompt now
Learn to interpret visibility reports
Create content that gets AI citations
Master advanced prompt strategies