# Get Agent Traffic Source: https://developers.scrunch.com/api-reference/agent-traffic/get-agent-traffic /api-reference/openapi.json get /{brand_id}/sites/{site_id}/agent-traffic Retrieve aggregated bot and AI agent traffic data for a specific site. This endpoint provides visibility into how AI agents and bots are accessing your web properties. Use it to analyze traffic patterns, identify top agents, and understand crawl behavior over time. ## Available Dimensions The following dimensions can be included in the `fields` parameter to group results: | Field | Description | |-------|-------------| | `date` | Daily timestamp for the traffic record | | `site` | The site domain being analyzed | | `path` | URL path on the site | | `agent_source` | The source/origin of the agent (e.g., OpenAI, Google, Anthropic) | | `agent_type` | Classification of the agent type | ## Metrics Traffic counts are automatically included in the response based on the selected dimensions. # Agent Traffic API: Monitor AI Bot Crawls Source: https://developers.scrunch.com/api-reference/agent-traffic/overview Aggregate AI bot and crawler traffic across your sites by date, path, agent source, and bot type to monitor retrieval, training, and indexing activity. ## Overview The Agent Traffic API provides aggregated analytics on AI bot activity across your websites. Track which AI platforms are crawling your content, what pages they access, and understand patterns in retrieval, training, and indexing behavior. This API is optimized for **time-series analysis** and **bot classification**, making it ideal for SEO teams, content strategists, and developers building AI visibility monitoring into their workflows. Each request returns aggregated bot traffic metrics grouped by the dimensions you select. *** ## What the Agent Traffic API includes The Agent Traffic API returns aggregated metrics including: * Request counts by bot source * Traffic patterns by date or week * Bot activity by page path * Classification by bot type (retrieval, training, indexer) These metrics can be grouped by dimensions including: * Date (day or week buckets) * Site domain * URL path * Agent source (e.g., chatgpt-user, claudebot, gptbot) * Agent type (retrieval, training, indexer) All results are **aggregated summaries** optimized for trend analysis and monitoring. *** ## When to use the Agent Traffic API Use the Agent Traffic API when you need: * Weekly or daily bot traffic reporting * Trend analysis of AI crawler behavior over time * Path-level breakdowns of bot activity * Bot classification by retrieval vs training purposes * Data for SEO dashboards monitoring AI visibility * Automated alerts based on traffic patterns The Agent Traffic API is designed to answer questions like: "Which AI bots are crawling my content?" and "How is bot traffic trending across different sections of my site?" *** ## When not to use the Agent Traffic API The Agent Traffic API is not appropriate if you need: * Raw access log entries * Individual request details (user agents, IP addresses, timestamps) * Real-time streaming data * Non-bot traffic analytics For CDN setup and log configuration, see the [Agent Traffic Integration Guide](/integrations/agent-traffic). *** ## Example query ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/sites/01JW849S5DJZ3CCE4DA6TFMYEY/agent-traffic?start_date=2025-01-01&end_date=2025-01-31&fields=date,agent_source,agent_type&time_bucket=week" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` **Response:** ```json theme={null} { "meta": { "start_date": "2025-01-01", "end_date": "2025-01-31", "time_bucket": "week" }, "data": [ { "date": "2025W01", "agent_source": "chatgpt-user", "agent_type": "retrieval", "requests": 1247 }, { "date": "2025W01", "agent_source": "claudebot", "agent_type": "training", "requests": 892 } ] } ``` *** ## Available dimensions | Field | Description | Example Values | | -------------- | ---------------- | ------------------------------------- | | `date` | Timestamp bucket | `20250115` (day) or `2025W03` (week) | | `site` | Domain | `example.com` | | `path` | URL path | `/blog/article` | | `agent_source` | Bot identifier | `chatgpt-user`, `claudebot`, `gptbot` | | `agent_type` | Bot category | `retrieval`, `training`, `indexer` | *** ## Time bucketing Control the granularity of date aggregation using the `time_bucket` parameter: * `day` (default): Daily aggregation with dates formatted as `YYYYMMDD` * `week`: Weekly aggregation with dates formatted as `YYYYWW` (ISO week number) Weekly buckets reduce result size and are recommended for long-range trend analysis. *** ## Path filtering Use the `path` parameter to filter results by URL path prefix: ```bash theme={null} # Only show bot traffic to blog articles ?path=/blog/ # Only show traffic to a specific section ?path=/products/widgets ``` Path matching uses prefix-based filtering with SQL LIKE patterns (`path LIKE '/blog/%'`). All user input is properly escaped to prevent SQL injection. *** ## Limits and performance considerations * Maximum rows per request: 100,000 * Default limit: 10,000 rows * Results are pre-aggregated for fast retrieval * Use pagination (`limit` and `offset`) for large result sets For best performance: * Use weekly bucketing when possible to reduce cardinality * Keep path filters specific to reduce result size * Request only the dimensions you need *** ## Security and validation The Agent Traffic API implements strict security measures: * **Site ID validation**: All site IDs are validated against ULID format using regex * **Parameter validation**: All query parameters are validated before SQL generation * **SQL injection prevention**: Path filters use escaped LIKE patterns with no direct string concatenation * **Authentication**: All requests require valid bearer token authentication *** ## Best practices * Use `time_bucket=week` for trend analysis spanning more than 30 days * Filter by `path` when analyzing specific site sections * Group by `agent_type` to distinguish retrieval bots from training crawlers * Run separate queries for different reporting needs rather than over-selecting dimensions * Monitor `agent_source` trends to identify new AI platforms crawling your content *** ## Typical use cases Teams commonly use the Agent Traffic API to: * Monitor which AI platforms are indexing their content * Identify pages with high bot traffic for SEO optimization * Track changes in crawler behavior after content updates * Build dashboards showing AI visibility by site section * Alert on unusual bot traffic patterns * Analyze the impact of robots.txt changes on AI crawler access *** ## Prerequisites Before using the Agent Traffic API, you must: 1. Configure your CDN or hosting provider to send access logs to Scrunch 2. Verify your site is properly configured in your Scrunch account 3. Obtain your site ID from the Scrunch dashboard Configure your CDN integration → # Send Custom Agent Traffic Events Source: https://developers.scrunch.com/api-reference/agent-traffic/post-custom-web-traffic POST https://webhooks.scrunchai.com/v1/sites/{site_id}/platforms/custom/web-traffic POST AI bot and agent traffic events from any web host, CDN, or edge function to Scrunch using the custom web-traffic ingestion endpoint. Send bot and AI agent traffic data from any platform to Scrunch AI. This endpoint accepts traffic events in JSON or NDJSON format and automatically classifies bots based on user agent strings. ## Endpoint ``` POST https://webhooks.scrunchai.com/v1/sites/{site_id}/platforms/custom/web-traffic ``` ## Authentication Authenticate using the `X-Api-Key` header with a JWT token provided in the Scrunch AI dashboard when creating a site with the "API" platform. To generate the `X-Api-Key`, add a new website on the Agent Traffic page and select `API` as your platform. ```bash theme={null} X-Api-Key: ``` ## Path parameters | Parameter | Type | Required | Description | | --------- | ------ | -------- | ---------------------------------------------------- | | `site_id` | string | Yes | The Site ID (ULID format) assigned in the dashboard. | The `platform_id` is always `custom` for this endpoint. ## Request headers | Header | Value | Required | Description | | -------------- | -------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------- | | `X-Api-Key` | `` | Yes | Authentication token from the dashboard. | | `Content-Type` | `application/json` or `application/x-ndjson` | Yes | Use `application/json` for a single event, or `application/x-ndjson` for multiple events (one JSON object per line). | ## Request body The body can be either a **single JSON object** or **NDJSON** (newline-delimited JSON, one object per line). ### Fields | Field | Type | Required | Description | | --------------- | --------------- | -------- | ------------------------------------------------------------------ | | `domain` | string | Yes | The domain of the site (e.g. `example.com`). | | `user_agent` | string | Yes | The full User-Agent string of the request. | | `url` | string | Yes | The full URL that was requested (e.g. `https://example.com/page`). | | `path` | string | Yes | The URL path (e.g. `/page`). | | `method` | string | Yes | The HTTP method (e.g. `GET`, `POST`). | | `status_code` | integer | Yes | The HTTP response status code (e.g. `200`, `404`). | | `timestamp` | integer / float | Yes | Unix epoch timestamp in **seconds** (e.g. `1700000000`). | | `response_time` | integer | No | Response time in milliseconds. | | `ip` | string | No | The IP address of the client making the request. | ## Example: single event (JSON) ```bash theme={null} curl -X POST "https://webhooks.scrunchai.com/v1/sites/{site_id}/platforms/custom/web-traffic" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY" \ -d '{ "domain": "example.com", "user_agent": "Mozilla/5.0 (compatible; GPTBot/1.0; +https://openai.com/gptbot)", "url": "https://example.com/blog/post", "path": "/blog/post", "method": "GET", "status_code": 200, "timestamp": 1700000000, "response_time": 120, "ip": "203.0.113.1" }' ``` ## Example: batch events (NDJSON) Send multiple events in a single request using newline-delimited JSON. Each line is a complete JSON object. ```bash theme={null} curl -X POST "https://webhooks.scrunchai.com/v1/sites/{site_id}/platforms/custom/web-traffic" \ -H "Content-Type: application/x-ndjson" \ -H "X-Api-Key: YOUR_API_KEY" \ -d '{"domain":"example.com","user_agent":"Mozilla/5.0 (compatible; GPTBot/1.0)","url":"https://example.com/page-1","path":"/page-1","method":"GET","status_code":200,"timestamp":1700000000} {"domain":"example.com","user_agent":"Mozilla/5.0 (compatible; ClaudeBot/1.0)","url":"https://example.com/page-2","path":"/page-2","method":"GET","status_code":200,"timestamp":1700000060,"response_time":95,"ip":"198.51.100.42"}' ``` ## Responses | Status Code | Description | | ----------- | --------------------------------------------------------------------------- | | 200 | Events accepted and queued for processing. | | 401 | Unauthorized — invalid or missing API key. | | 422 | Validation error — check the request body against the schema above. | | 429 | Rate limited — wait and retry. Respect the `Retry-After` header if present. | | 500 | Internal server error. | ### Success response (200) ```json theme={null} { "status": "ok" } ``` ## Notes * **Batch size**: For NDJSON batches, keep each request under \~1 MB uncompressed. * **Timestamp**: Must be a Unix epoch in seconds. Both integers and floats are accepted. Invalid timestamps will fall back to the current server time. * **Bot detection**: The `user_agent` field is used to automatically identify and classify the bot/AI agent. Pass the original User-Agent string from the incoming request. * **Activation**: After creating a site with the "API" platform in the dashboard, it starts in "pending" status. Once the first valid request is received, the site automatically transitions to "active" within 5 minutes. ## Best practices * Use NDJSON for batch uploads to reduce request overhead * Keep batch sizes under 1 MB for optimal performance * Always pass the original User-Agent string for accurate bot classification * Monitor response status codes and implement retry logic for 429 and 500 errors * Use the `response_time` field to track performance metrics alongside bot traffic # Disable AI Referrals Connection Source: https://developers.scrunch.com/api-reference/ai-referrals/disable-ai-referrals-connection /api-reference/openapi.json delete /{brand_id}/ai-referrals/connections/{connection_id} Soft-disable a connection. Previously pushed events are retained but further pushes are rejected with `410 Gone` and the dashboard stops reading from this connection. # List AI Referrals Connections Source: https://developers.scrunch.com/api-reference/ai-referrals/list-ai-referrals-connections /api-reference/openapi.json get /{brand_id}/ai-referrals/connections List AI Referrals push connections registered for this brand. Scope is limited to push connections only — Google Analytics integrations live in a separate system and are not returned here, even though they can block a register call with `409`. # AI Referrals API: Push AI-Sourced Traffic Data Source: https://developers.scrunch.com/api-reference/ai-referrals/overview Push pre-aggregated daily referral events from Adobe Analytics and other tools into Scrunch to power the AI Traffic dashboard and Site Map metrics. ## Overview The AI Referrals API ingests pre-aggregated daily traffic that originated from AI assistants (ChatGPT, Claude, Perplexity, and so on) into Scrunch. Use it when your source of truth for web analytics is **Adobe Analytics** or another tool you'd like to push from on a schedule, rather than connecting Google Analytics directly. Once a connection is registered and events start landing, the AI Traffic dashboard and the Site Map's `ai_referrals` metric prefer push data over any live-queried Google Analytics integration for the same website. *** ## When to use the AI Referrals API Use this API when you need to: * Send AI-sourced traffic from **Adobe Analytics** into Scrunch on a daily schedule. * Backfill historical AI referral data from any pre-aggregated source. * Power the AI Traffic dashboard for brands that don't use Google Analytics. If your team uses **Google Analytics 4**, connect it through the in-app integration instead — you don't need this API. A brand cannot have both a Google Analytics integration and an active AI Referrals push connection on the same website at the same time. *** ## How it works 1. **Register a connection** for the `(brand, website, provider)` you'll push from. Connections are scoped to one website each; register multiple connections if you push for several domains. 2. **Push events** in batches against that connection. Each event is one row of pre-aggregated daily metrics — pageviews, sessions, transactions, and revenue — keyed by date, referrer, and page. 3. **Read results** on the AI Traffic dashboard and via the Sitemap API's `ai_referrals` totals. Pushes are **idempotent**. The upsert key is `(date, raw_referrer_value, raw_page_value)` — resending the same tuple replaces the prior values, so retries and corrections are safe. *** ## Authentication All endpoints use Bearer-token authentication. Connection writes require the `configure` scope; listing requires the `query` scope. ```bash theme={null} export SCRUNCH_API_TOKEN="your-key" ``` Generate a key under **Organization → Settings → API Keys** in the Scrunch dashboard. *** ## Endpoints | Method | Path | Purpose | | -------- | ------------------------------------------------------------- | -------------------------------------------------------- | | `POST` | `/{brand_id}/ai-referrals/connections` | Register a push connection for one website and provider. | | `GET` | `/{brand_id}/ai-referrals/connections` | List the brand's push connections. | | `DELETE` | `/{brand_id}/ai-referrals/connections/{connection_id}` | Soft-disable a connection. | | `POST` | `/{brand_id}/ai-referrals/connections/{connection_id}/events` | Push a batch of pre-aggregated daily events. | The list endpoint returns push connections only. Google Analytics integrations live in a separate system and don't appear here, even when they're the reason a register call returned `409`. *** ## Supported providers The MVP allow-list is: * `adobe_analytics` More providers will be added behind the same `provider` field — your code doesn't need to change when the allow-list grows. *** ## Event schema Each event is one pre-aggregated daily row. | Field | Type | Required | Description | | -------------------- | --------------------- | -------- | ------------------------------------------------------------------------------------------------------------------ | | `date` | string (`YYYY-MM-DD`) | Yes | UTC calendar day the metrics cover. | | `raw_referrer_value` | string | Yes | Raw referrer from the source tool (e.g. `chatgpt.com`). Normalized server-side against the AI platform allow-list. | | `raw_page_value` | string | Yes | Raw page identifier — URL path for GA-shape tools, page name for Adobe unless a URL eVar is configured. | | `pageviews` | integer | No | Pageviews for the row. Must be ≥ 0. | | `sessions` | integer | No | Sessions for the row. Must be ≥ 0. | | `transactions` | integer | No | Completed transactions, when available. | | `purchase_revenue` | number | No | Revenue attributed to the row. | | `batch_id` | string | No | Optional client-supplied identifier for traceability. | *** ## Example: register a connection ```bash theme={null} curl -X POST "https://api.scrunchai.com/v1/1234/ai-referrals/connections" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "website": "example.com", "provider": "adobe_analytics" }' ``` **Response:** ```json theme={null} { "id": "01JX2Y6E8H1AKQ8V0W7G4D9SXT", "brand_id": 1234, "website": "example.com", "provider": "adobe_analytics", "status": "active", "created_at": "2026-05-24T12:00:00Z", "last_pushed_at": null, "last_push_error": null } ``` Save the returned `id` — you'll use it as `connection_id` on every push. *** ## Example: push a batch (JSON array) ```bash theme={null} curl -X POST \ "https://api.scrunchai.com/v1/1234/ai-referrals/connections/01JX2Y6E8H1AKQ8V0W7G4D9SXT/events" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '[ { "date": "2026-05-20", "raw_referrer_value": "chatgpt.com", "raw_page_value": "/blog/launch-notes", "pageviews": 412, "sessions": 298, "transactions": 7, "purchase_revenue": 1842.50 }, { "date": "2026-05-20", "raw_referrer_value": "perplexity.ai", "raw_page_value": "/pricing", "pageviews": 88, "sessions": 71 } ]' ``` **Response:** ```json theme={null} { "accepted": 2, "rejected": 0, "errors": [] } ``` Events whose `raw_referrer_value` doesn't match Scrunch's AI platform allow-list are counted in `rejected` rather than failing the whole batch. *** ## Example: push a batch (NDJSON) For larger batches, send newline-delimited JSON to reduce parser overhead: ```bash theme={null} curl -X POST \ "https://api.scrunchai.com/v1/1234/ai-referrals/connections/01JX2Y6E8H1AKQ8V0W7G4D9SXT/events" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/x-ndjson" \ --data-binary $'{"date":"2026-05-20","raw_referrer_value":"chatgpt.com","raw_page_value":"/blog/a","pageviews":12}\n{"date":"2026-05-20","raw_referrer_value":"claude.ai","raw_page_value":"/blog/b","pageviews":3}' ``` *** ## Limits * **10,000 events per batch.** Larger batches return `413 Payload Too Large` — split and retry. * **5 MB request body.** Same `413` behavior. * One **active** connection per `(brand_id, website)`. Disable the existing connection or use a different website before re-registering. *** ## Status codes | Status | Meaning | | ------ | ----------------------------------------------------------------------------------- | | `200` | Batch accepted. The response body reports `accepted` and `rejected` counts. | | `201` | Connection registered. | | `400` | Malformed payload, invalid provider, or empty body. | | `404` | Brand or connection not found. | | `409` | A connection or conflicting integration already exists for this `(brand, website)`. | | `410` | Connection is disabled — re-register before pushing again. | | `413` | Batch exceeds the 10,000-event or 5 MB cap. | | `422` | One or more events failed schema validation. The body includes per-row errors. | *** ## Best practices * **Push once per day** after your source tool has finalized the prior day's data. The upsert key makes re-pushes safe, but daily granularity is enough for the dashboard. * **Send raw referrer values** straight from your source tool — don't pre-normalize. Scrunch maps them to AI platforms server-side and that mapping evolves over time. * **Include `batch_id`** when you can. It makes it easier to correlate a push with your ETL run if you need to investigate later. * **Back off on `429`/`5xx`** with exponential retry. Pushes are idempotent on the upsert key. * **Don't mix providers** on one connection. Register one connection per `(website, provider)`. # Push AI Referrals Events Source: https://developers.scrunch.com/api-reference/ai-referrals/push-ai-referrals-events /api-reference/openapi.json post /{brand_id}/ai-referrals/connections/{connection_id}/events Push a batch of pre-aggregated daily AI-referral events for a registered connection. Accepts `application/json` (a JSON array of events) or `application/x-ndjson` (one event per line). The upsert key is `(date, raw_referrer_value, raw_page_value)` — re-sending the same tuple replaces the prior values, so backfills and corrections are safe to retry. Limits: - Maximum 10,000 events per batch. - Maximum 5 MB request body. # Register AI Referrals Connection Source: https://developers.scrunch.com/api-reference/ai-referrals/register-ai-referrals-connection /api-reference/openapi.json post /{brand_id}/ai-referrals/connections Register an AI Referrals push connection for a (brand, website, provider) tuple. Events can only be pushed once a connection exists. A brand cannot have both a Google Analytics integration and an active AI Referrals push connection for the same website — the conflicting integration must be disabled first. MVP provider allow-list: `adobe_analytics`. # Archive Competitor Source: https://developers.scrunch.com/api-reference/archive-competitor /api-reference/openapi.json delete /brands/{brand_id}/competitors/{competitor_id} Archive a competitor # Archive Persona Source: https://developers.scrunch.com/api-reference/archive-persona /api-reference/openapi.json delete /brands/{brand_id}/personas/{persona_id} Archive a persona # Archive Prompt Source: https://developers.scrunch.com/api-reference/archive-prompt /api-reference/openapi.json delete /{brand_id}/prompts/{prompt_id} Archives a prompt (soft delete). The prompt will no longer be tracked but historical data is preserved. Requires the `configure` scope. # Bulk Render Optimized Pages Source: https://developers.scrunch.com/api-reference/axp-render/bulk-render-optimized-pages /api-reference/openapi.json post /orchestration/render-bulk/{brand_id}/sites/{site_id} Queue render jobs for a list of paths on a registered AXP site. Each path is fetched, sanitized, and persisted as an AXP optimized page asynchronously, so the endpoint returns immediately with one job entry per input path. Paths are normalized (trimmed and given a leading slash) and deduplicated before queueing. A path that already has an in-flight job on the same site coalesces onto that job, so the same batch can be retried safely. Inputs are capped at 100 paths per call. # AXP Render API: Queue Optimized Page Renders Source: https://developers.scrunch.com/api-reference/axp/overview Queue asynchronous render jobs that fetch, sanitize, and persist pages on your AXP site so optimized content is ready to deploy from one API call. ## Overview The AXP Render API queues asynchronous render jobs for paths on a registered AXP site. Each job fetches the live page from your origin, strips noise (scripts, styles, inline event handlers, base64 images), and persists the cleaned HTML as an optimized page that you can then edit, version, and deploy from the Scrunch dashboard. Use it to seed an AXP site with content programmatically — for example, after a sitemap import or when onboarding a new domain — without clicking through **Add Content** for each path. Renders run in the background. The endpoint responds as soon as jobs are queued; you can correlate the returned `job_id` with the page that appears in the AXP content list once the job completes. *** ## When to use the AXP Render API Use this API when you need to: * Bulk-seed an AXP site with optimized pages for a known list of paths. * Re-render an archived path to reactivate it as an Active page. * Refresh stale renders after a marketing-site redeploy, on a schedule. For interactive, one-off renders, use **Add Content → Render from site** in the Scrunch dashboard. For audit-then-optimize-then-deploy workflows, use the [Optimize and Deploy API](/api-reference/optimize-deploy) instead. *** ## Endpoint | Method | Path | Purpose | | ------ | ---------------------------------------------------------- | ------------------------------------------------ | | POST | `/v2/orchestration/render-bulk/{brand_id}/sites/{site_id}` | Queue render jobs for a list of paths on a site. | The endpoint requires a bearer token with the `configure` scope. See [Authentication](/getting-started/authentication). *** ## Request | Field | Type | Required | Description | | ------- | ---------- | -------- | -------------------------------------------------------------------------------------------------------------- | | `paths` | `string[]` | Yes | Paths to render. Each entry is trimmed and given a leading slash if missing. Capped at **100 paths** per call. | ### Path normalization and deduplication Before queueing, the API normalizes each path: * Surrounding whitespace is stripped. * A leading `/` is added when missing. * Duplicates after normalization are dropped, preserving input order. So `["/blog", "blog", " /blog "]` queues a single job for `/blog`. ### Coalescing in-flight jobs If a path already has a `pending` or `running` job on the same site, the request returns the existing `job_id` instead of queueing a new one. This makes the endpoint safe to retry with the same batch — you won't end up with duplicate renders or duplicate optimized pages. *** ## Response The response is an array of items, one per unique path: | Field | Type | Description | | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- | | `path` | `string` | The normalized path the job was queued for. | | `job_id` | `integer` | Identifier of the render job. Use it for correlation in logs. | | `status` | `string` | Job status at response time. `pending` means a fresh job was queued; `running` means the call coalesced onto an existing job. | Job status values: `pending`, `running`, `succeeded`, `failed`, `cancelled`. *** ## Example: queue renders ```bash theme={null} curl -X POST \ "https://api.scrunchai.com/v2/orchestration/render-bulk/1234/sites/01JEXAMPLE00000000000000" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "paths": [ "/", "/pricing", "/blog/launch-announcement" ] }' ``` **Response:** ```json theme={null} [ { "path": "/", "job_id": 1842, "status": "pending" }, { "path": "/pricing", "job_id": 1843, "status": "pending" }, { "path": "/blog/launch-announcement", "job_id": 1801, "status": "running" } ] ``` In this response the first two paths were freshly queued, and `/blog/launch-announcement` coalesced onto an in-flight job (`1801`) from an earlier call. *** ## Errors | Status | When | | ------ | ---------------------------------------------------------------------------------------------------------------------------------------- | | `400` | The site is not active for AXP, or has no domain configured. | | `404` | No site with the supplied ULID exists for the brand. | | `422` | The request body failed validation (empty `paths`, more than 100 entries, path longer than 2048 chars). | | `502` | Jobs were persisted but at least one dispatch to the background worker failed. The affected jobs are marked `failed`; retry those paths. | *** ## Limits and behavior * Maximum **100 paths** per request. Split larger batches into multiple calls. * Each path must be 1–2048 characters after normalization. * The target site must have `axp_status` set to `active` and a configured domain. * Re-rendering a path that exists as an archived page reactivates it as **Active** and logs a `CONTENT_CREATED` event. * Pages rendered through this API show up in the AXP content list with the same statuses as renders started from the dashboard. *** ## Best practices * Poll the dashboard or correlate job IDs from your logs to confirm completion — `succeeded` jobs produce an optimized page you can deploy. * Retry idempotently. Because in-flight jobs coalesce, the same batch can be sent again after a network error without creating duplicate work. * Pair with the [Sitemap API](/api-reference/sitemap/overview) to source the path list. Filter by `is_priority=true` to seed AXP with your most important pages first. # Configuration API: Manage Brands and Prompts Source: https://developers.scrunch.com/api-reference/configuration/overview Create brands, manage competitors and personas, and configure tracking prompts via the Scrunch Configuration API to automate client onboarding. The Configuration API lets you manage Scrunch brands at scale.\ It is most commonly used by: * Agencies onboarding dozens or hundreds of clients * Enterprise teams automating persona and keyword setup * Internal tools (brand creation, batch updates, auditing) *** ## What you can configure ### Brands * Name, alternative names * Website + alternative websites * Competitors * Personas * Key topics ### Prompts * Text * Stage * Tags * Personas * Platforms *** ## Example: Create a brand ```bash theme={null} curl -X POST "https://api.scrunchai.com/v1/brands" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Spirit Airlines", "website": "https://spirit.com", "description": "Low cost air carrier." }' ``` *** ## Case-sensitive name matching By default, Scrunch matches brand and competitor names against AI responses case-insensitively, so `"spirit airlines"`, `"Spirit Airlines"`, and `"SPIRIT AIRLINES"` all count as mentions. For names that are common words, acronyms, or stylized in a specific case (for example, `NeXT`, or `LUSH`), enable case-sensitive matching to avoid false positives. Set `case_sensitive: true` on a brand or competitor to require exact-case matches for `name` and `alternative_names`. The flag defaults to `false` and is available on: * `POST /brands` — on the brand body and on each entry in `competitors[]` * `PATCH /brands/{brand_id}` — on the brand and on each competitor in the replacement list * `POST /brands/{brand_id}/competitors` and `PUT /brands/{brand_id}/competitors/{competitor_id}` * `GET` responses for brands and competitors return the current value ```bash theme={null} curl -X POST "https://api.scrunchai.com/v1/brands" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "LUSH", "website": "https://lush.com", "case_sensitive": true, "competitors": [ { "name": "The Body Shop", "case_sensitive": false } ] }' ``` Changing `case_sensitive` on an existing brand triggers a re-evaluation of historical responses against the new matching rule. ## Domain uniqueness across brand and competitors Each domain can only be classified one way within a brand — either as the brand's own or as one specific competitor's. This keeps citation owner classification (`brand` / `competitor` / `other`) deterministic. Scrunch normalizes every configured URL by stripping the scheme, `www.`, query, fragment, and trailing slash, and lowercasing it. The brand's primary `website` is compared by domain only, while `alternative_websites` and competitor `websites` keep their path — so `example.com/a` and `example.com/b` on two different owners do not conflict. If a write would assign the same normalized domain to two different owners (for example, the brand's `website` and a competitor's `websites`, or two competitors), the request is rejected with HTTP `409` and a `detail` describing where the domain is already used. The check applies to: * `POST /brands` and `PATCH /brands/{brand_id}` (brand `website`, `alternative_websites`, and the replacement `competitors[]`) * `POST /brands/{brand_id}/competitors` and `PUT /brands/{brand_id}/competitors/{competitor_id}` Only newly introduced conflicts are blocked, so unrelated edits to a brand that already contains a legacy collision still save. To move a domain between owners, remove it from the current owner in the same request that adds it to the new one. ```json theme={null} { "detail": "example.com is already configured as the competitor 'Acme' for this brand. A domain can only be classified one way (brand vs. competitor)." } ``` ## Alternative names limit Each brand and competitor accepts up to **100 entries** in `alternative_names`. Submitting more returns a `422 Unprocessable Entity` with the message: ``` alternative_names cannot exceed 100 entries (got N); remove some before saving ``` The cap is enforced on every write endpoint that accepts `alternative_names`, including: * `POST /v1/brands` and `PATCH /v1/brands/{brand_id}` (brand body and each competitor) * `POST /v1/brands/{brand_id}/competitors` and `PUT /v1/brands/{brand_id}/competitors/{competitor_id}` If you previously sent more than 100 aliases, the collection layer silently kept only the 100 shortest. Trim your list before retrying so you control which aliases are retained. ```bash theme={null} curl -X POST "https://api.scrunchai.com/v1/brands" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Spirit Airlines", "website": "https://spirit.com", "description": "Low cost air carrier.", "alternative_names": ["Spirit", "Spirit Air", "NK"] }' ``` ## Excluded names Use `excluded_names` to list phrases that should never count as a mention of a brand or competitor, even when the phrase contains a configured name as a word. This lets a brand named `Caliber` match `Caliber Collision` while ignoring unrelated entities like `Caliber Car Wash` or `Caliber Fitness`. Scrunch blanks every word-boundary occurrence of each excluded phrase before searching the response for this entity's names. Position and other span-based metrics are unaffected because masked spans are replaced with equal-length whitespace. Historical responses are re-evaluated when `excluded_names` changes, so metrics update without a manual backfill. `excluded_names` is a list of strings and is available on: * `POST /v1/brands` — on the brand body and on each entry in `competitors[]` * `PATCH /v1/brands/{brand_id}` — on the brand and on each competitor in the replacement list * `POST /v1/brands/{brand_id}/competitors` and `PUT /v1/brands/{brand_id}/competitors/{competitor_id}` * `GET` responses for brands and competitors return the current value ```bash theme={null} curl -X POST "https://api.scrunchai.com/v1/brands" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Caliber", "website": "https://caliber.com", "excluded_names": ["Caliber Car Wash", "Caliber Fitness", "Caliber Armor"] }' ``` Each brand and competitor accepts up to **100 entries** in `excluded_names`. Submitting more returns a `422 Unprocessable Entity` with: ``` excluded_names cannot exceed 100 entries (got N); remove some before saving ``` Scrunch rejects an exclusion that equals the entity's own `name` or any of its `alternative_names`, since either would remove every mention of the entity. Remove the alternative name instead of excluding it. The check runs after Scrunch normalizes punctuation, so `Caliber.` and `Caliber` are treated as the same phrase. ## Example: Add a prompt ```bash theme={null} curl -X POST "https://api.scrunchai.com/v1/1234/prompts" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "text": "What are the best budget airlines?", "tags": ["budget"], "platforms": ["chatgpt", "perplexity"] }' ``` ## Listing prompts `GET /{brand_id}/prompts` returns active prompts by default. Pass the `status` query parameter to include archived prompts: | Value | Returns | | ------------------ | ------------------------- | | `active` (default) | Currently tracked prompts | | `archived` | Soft-deleted prompts only | | `all` | Both active and archived | ```bash theme={null} # All prompts including archived ones curl "https://api.scrunchai.com/v1/$BRAND_ID/prompts?status=all" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` Each prompt in the response includes: * `branded` — `true` if the prompt mentions the brand * `favorite` — `true` if marked as a favorite in the dashboard * `status` — `active` or `archived` `GET /{brand_id}/prompts/{prompt_id}` returns archived prompts as well, so check the `status` field if you only want active ones. *** ## Reusing an archived persona name When you `PATCH /brands/{brand_id}` with personas, the list represents the full desired state: existing personas not included are archived. If you later submit a persona without an `id` and the `name` matches a previously archived persona on the same brand, Scrunch reactivates the archived record instead of failing on the unique-name constraint. Its `status` returns to `active` and the `description` is replaced with the value you provide. ```bash theme={null} curl -X PATCH "https://api.scrunchai.com/v1/brands/$BRAND_ID" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "personas": [ { "name": "Budget Traveler", "description": "Price-sensitive consumer" } ] }' ``` If `Budget Traveler` was previously archived on this brand, the call reactivates that persona and updates its description. To update an existing active persona instead, include its `id`. *** ## Persona limits when creating a brand `POST /brands` accepts an optional `personas` array. Each plan caps how many personas you can attach to a single brand. If the array is longer than your plan allows, the request is rejected before the brand is created — no partial brand is saved. When the limit is exceeded, the API returns `429 Too Many Requests` with a `quota_exceeded` error: ```json theme={null} { "detail": { "error": "quota_exceeded", "feature_key": "brand.personas.count", "limit": 3, "used": 5, "message": "This plan allows up to 3 personas per brand; received 5." } } ``` To recover, trim the `personas` array to `limit` entries or fewer and retry the request. To find your plan's limit, inspect the `limit` field in the error response or contact your account team. Personas can also be added or replaced after a brand is created via `POST /brands/{brand_id}/personas` and `PATCH /brands/{brand_id}`. The cap is currently enforced only at brand creation. *** ### Notes To update prompt text, delete the old prompt and create a new one. Only tags and platforms can be updated in-place. Explore the API reference → # Create Brand Source: https://developers.scrunch.com/api-reference/create-brand /api-reference/openapi.json post /brands Create a new brand # Create Competitor Source: https://developers.scrunch.com/api-reference/create-competitor /api-reference/openapi.json post /brands/{brand_id}/competitors Create a new competitor # Create Page Audits Source: https://developers.scrunch.com/api-reference/create-page-audits /api-reference/openapi.json post /{brand_id}/page-audits Create one or more page audits # Create Persona Source: https://developers.scrunch.com/api-reference/create-persona /api-reference/openapi.json post /brands/{brand_id}/personas Create a new persona # Create Prompt Source: https://developers.scrunch.com/api-reference/create-prompt /api-reference/openapi.json post /{brand_id}/prompts Creates a new prompt with variants for the specified platforms. Requires the `configure` scope. **Behavior:** - `stage` is optional. If omitted, the journey stage is auto-classified against your brand's active stages using an LLM. - If `stage` is provided, it must match one of your brand's active stages (case-sensitive display name). An unknown value returns `400`. An explicit stage is treated as a manual assertion and won't be overwritten by later re-classification. - Creates variants for each specified platform. - Reactivates an archived prompt if a duplicate exists. - Dispatches collection events to begin tracking. # Get Competitor Source: https://developers.scrunch.com/api-reference/get-competitor /api-reference/openapi.json get /brands/{brand_id}/competitors/{competitor_id} Get a competitor by ID # Get Page Audit Source: https://developers.scrunch.com/api-reference/get-page-audit /api-reference/openapi.json get /{brand_id}/page-audits/{page_audit_id} Get a specific page audit by ID # Get Persona Source: https://developers.scrunch.com/api-reference/get-persona /api-reference/openapi.json get /brands/{brand_id}/personas/{persona_id} Get a persona by ID # Scrunch API Introduction and Authentication Source: https://developers.scrunch.com/api-reference/introduction Programmatic access to AI visibility metrics, raw AI responses, brand configuration, and reporting pipelines through the Scrunch REST APIs. # Scrunch API Overview Scrunch gives you programmatic access to the same data and configuration that powers the Scrunch dashboard.\ Use these APIs to query AI visibility metrics, ingest raw AI responses, automate onboarding, update brand configuration, and build custom reporting pipelines. *** ## What you can do with the Scrunch API Pull metrics like brand presence, sentiment score, position, competitor presence, and source citations across platforms. Access every response Scrunch collects, including text, citations, persona info, platform, sentiment, and competitor details. Programmatically create brands, update configuration, manage prompts, and power internal tooling. *** ## Authentication All endpoints require a Bearer token.\ You can create tokens under **Organization → Settings → API Keys** in the Scrunch dashboard. ```bash theme={null} export SCRUNCH_API_TOKEN="your-key" curl -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ https://api.scrunchai.com/v1/brands ``` Brand-scoped keys can only access specific brands. Organization-scoped keys can access and configure all brands. ## Quickstarts Learn how to retrieve brand presence, sentiment, and other key metrics. Fetch full response text, citations, competitor details, and more. Connect Scrunch to Looker Studio and other BI tools. ## API References The full set of endpoints is auto-generated from our OpenAPI specification. Browse Query, Responses, and Configuration endpoints. # List Brands Source: https://developers.scrunch.com/api-reference/list-brands /api-reference/openapi.json get /brands List available brands # List Competitors Source: https://developers.scrunch.com/api-reference/list-competitors /api-reference/openapi.json get /brands/{brand_id}/competitors List competitors for a brand # List Page Audits Source: https://developers.scrunch.com/api-reference/list-page-audits /api-reference/openapi.json get /{brand_id}/page-audits List page audits in reverse chronological order # List Personas Source: https://developers.scrunch.com/api-reference/list-personas /api-reference/openapi.json get /brands/{brand_id}/personas List personas for a brand # List Prompts Source: https://developers.scrunch.com/api-reference/list-prompts /api-reference/openapi.json get /{brand_id}/prompts Returns a paginated list of active prompts for the specified brand, including their variants, tags, and topics. Use this endpoint to retrieve all prompts configured for AI visibility tracking. # List Responses Source: https://developers.scrunch.com/api-reference/list-responses /api-reference/openapi.json get /{brand_id}/responses Returns AI responses (observations) with full evaluation data, citations, and competitor analysis. Each response represents a single AI-generated answer to a tracked prompt. This endpoint provides the raw response data needed for deep analysis, audits, and research. For aggregated metrics, use the Query API instead. **Response data includes:** - Full response text from the AI platform - Brand evaluation (presence, sentiment, position) - Competitor evaluations with individual metrics - Citations with source classification (brand/competitor/other) - Prompt and persona context # Create Optimize And Deploy Pipeline Source: https://developers.scrunch.com/api-reference/orchestration/create-optimize-and-deploy-pipeline /api-reference/openapi.json post /orchestration/optimize-and-deploy/{brand_id} Create an orchestrated pipeline: audit pages, optimize content, and deploy to AXP # Get Pipeline Status Source: https://developers.scrunch.com/api-reference/orchestration/get-pipeline-status /api-reference/openapi.json get /orchestration/optimize-and-deploy/{brand_id}/{token} Get the status of an optimize-and-deploy pipeline by token # Optimize and Deploy Pipeline API Overview Source: https://developers.scrunch.com/api-reference/orchestration/overview Run a single async pipeline to audit pages, optimize content for AI search visibility, and deploy results to AXP with polling or webhooks. ## One endpoint to rule them all The Optimize and Deploy API lets you run a multi-stage pipeline that audits your pages, optimizes their content for AI search visibility, and optionally deploys the results to AXP — all from a single API call. One endpoint to bind your audit, optimization, and deployment workflows together. Each pipeline is asynchronous. You submit URLs, receive tracking tokens, and then poll for status or receive webhook callbacks as each stage completes. The Optimize and Deploy API is currently in **early access** and available on request. Contact your Customer Success representative to get access enabled for your organization. *** ## How it works The pipeline chains three Scrunch products together. Each stage is optional — use only what you need. ```mermaid theme={null} flowchart LR A["Submit URLs"] --> B["🔍 Site Audit"] B --> C{"optimize?"} C -- "true" --> D["✨ Content Optimizer"] C -- "false" --> G["✅ Done"] D --> E{"deploy_axp?"} E -- "true" --> F["🚀 AXP Deploy"] E -- "false" --> G F --> G ``` | Product | Pipeline stage | What it does | Required? | | --------------------- | -------------- | --------------------------------------------------------------------------------------- | ---------------------------------- | | **Site Audit** | `audit` | Evaluates AI discoverability: robots.txt, bot access, content quality, content delivery | Always runs | | **Content Optimizer** | `optimizing` | Rewrites page content to improve AI visibility for target prompts and personas | Set `optimize: true` | | **AXP (stage)** | `optimizing` | Stages optimized content to AXP for review without publishing live | Set `stage_axp: true` + `site_id` | | **AXP (deploy)** | `deploying` | Publishes optimized content to your AXP site as a new version | Set `deploy_axp: true` + `site_id` | ### Configuration per product Each product in the pipeline has its own configuration: * **Site Audit** — runs automatically on each URL, no extra config needed * **Content Optimizer** — optionally configure `target_prompts`, `target_personas`, `target_sources`, `override_suggestions`, and per-URL `custom_instructions` * **AXP** — requires a `site_id` (the RegisteredSite ULID). All URLs must belong to the site's domain. Per-URL `retain_schema_types` controls which JSON-LD schema types are kept (omit to retain all) *** ## Pipeline stages Every URL you submit moves through these stages in order: | Stage | `orchestration_status` | What happens | | ------------ | ---------------------- | ----------------------------------------------------------------------------------------------- | | **Audit** | `audit` | Page is fetched and evaluated for AI discoverability (robots.txt, content quality, bot access) | | **Optimize** | `optimizing` | Content is analyzed and rewritten to improve AI visibility for your target prompts and personas | | **Deploy** | `deploying` | Optimized content is published to AXP as a new version | | **Done** | `completed` | All stages finished successfully | | **Error** | `failed` | Pipeline stopped at the failing stage | ```mermaid theme={null} stateDiagram-v2 [*] --> audit audit --> optimizing : optimize = true audit --> completed : optimize = false audit --> failed : error optimizing --> deploying : deploy_axp = true optimizing --> completed : deploy_axp = false optimizing --> failed : error deploying --> completed : success deploying --> failed : error ``` The optimize and deploy stages only run if you set `optimize: true` and `deploy_axp: true` in the request. With defaults, only the audit stage runs. To stage content for review without publishing live, set `stage_axp: true` instead of `deploy_axp` — see the [orchestration lifecycle guide](/guides/orchestration-lifecycle) for the stage-only flow. *** ## When to use it * You want to audit, optimize, and deploy pages without multiple API calls * You need batch processing across many URLs * You want webhook notifications when stages complete * You're building automated content optimization pipelines ## When not to use it * You only need audit results — use the **Site Audit API** directly * You want to query existing visibility data — use the **Query API** * You need manual control over each optimization — use the Scrunch dashboard *** ## Request patterns ### Simple: list of URLs Pass `urls` when every URL should use the same optimization configuration: ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/1234" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "urls": [ "https://example.com/page-a", "https://example.com/page-b" ], "optimize": true, "deploy_axp": true, "site_id": "01JEXAMPLE00000000000000" }' ``` ### Detailed: per-URL overrides Pass `requests` when individual URLs need different prompts, personas, or sources: ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/1234" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "requests": [ { "url": "https://example.com/page-a", "target_prompts": ["best budget airlines"], "target_personas": [{"name": "Budget Traveler"}] }, { "url": "https://example.com/page-b", "target_prompts": ["luxury travel options"] } ], "optimize": true, "deploy_axp": true, "site_id": "01JEXAMPLE00000000000000" }' ``` Provide either `urls` or `requests`, not both. The API will reject requests that include both fields. *** ## Tracking progress Each URL gets its own tracking token. Use it to poll for status: ```bash theme={null} curl "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/1234/01JABCTOKEN00000000000" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` The response includes the current `orchestration_status`, timestamps, and result data as it becomes available. For real-time updates without polling, configure webhooks to receive callbacks at each stage transition. Get notified when audits, optimizations, and deployments complete. *** ## Error codes When a pipeline fails, the response includes a structured error code. Use these to identify what went wrong and where: | Prefix | Stage | Example codes | | ------------- | ---------------- | -------------------------------------------------------------- | | `ORCH-INIT` | Initialization | Invalid URL, missing site\_id, domain mismatch, quota exceeded | | `ORCH-AUDIT` | Audit | Fetch failed, timeout, page not found | | `ORCH-OPT` | Optimization | No content to optimize, LLM failure, source fetch failed | | `ORCH-DEPLOY` | Deployment | Site not found, AXP publish failed | | `ORCH-HOOK` | Webhook delivery | Delivery failed, SSRF blocked, timeout | Each error includes a human-readable message and a short `error_hash` you can reference when contacting support. *** ## Relationship to other Scrunch products The Optimize and Deploy API is a composition layer that chains together three standalone Scrunch products: ```mermaid theme={null} flowchart TB subgraph "Optimize and Deploy API" direction LR SA["Site Audit API
Audit pages for
AI discoverability
"] CO["Content Optimizer
Rewrite content for
AI visibility
"] AXP["AXP
Deploy optimized
content at the edge
"] SA --> CO --> AXP end API["POST /orchestration/optimize-and-deploy"] --> SA AXP --> DONE["Results + Webhooks"] ``` * **Site Audit** is always the first stage. It runs the same checks as `POST /{brand_id}/page-audits`. * **Content Optimizer** uses audit results plus your target prompts and personas to generate optimized content. * **AXP** deploys the optimized content as a new version to your registered site. Each product can also be used independently outside of this pipeline. ### Dashboard visibility Everything the pipeline does is fully visible in the Scrunch dashboard — audit results, optimization runs, and AXP deployments all appear in their respective pages exactly as if they had been performed manually. AXP deployments are tracked in the **Version History** with full change tracking, and you can compare original vs. optimized content side by side. Go to the Optimize and Deploy Quickstart # Query Source: https://developers.scrunch.com/api-reference/query /api-reference/openapi.json get /{brand_id}/query Query the data API to retrieve aggregated observation data across multiple dimensions and metrics. This endpoint dynamically generates SQL queries based on the requested fields, allowing flexible aggregation for analytics and reporting workflows. The query endpoint returns pre-aggregated metrics grouped by the specified dimensions. Results are optimized for BI tools, reporting pipelines, and dashboards. # Query API: Aggregated AI Visibility Metrics Source: https://developers.scrunch.com/api-reference/query/overview Pull aggregated brand presence, position, sentiment, citation, and competitor metrics across AI platforms and date ranges from Scrunch. ## Overview The Query API provides aggregated access to Scrunch’s core AI visibility metrics. It is the same data that powers the Scrunch dashboard, exposed in a flexible, queryable format for analytics and reporting workflows. This API is optimized for **scale and performance**, making it ideal for BI tools, reporting pipelines, scheduled exports, and automation where response-level detail is not required. Each request returns pre-aggregated metrics based on the dimensions you select. *** ## What the Query API includes The Query API returns aggregated metrics such as: * Brand presence percentage * Brand position score * Brand sentiment score * Competitor presence percentage * Sub-brand presence, position, and sentiment * Citation rate, share of voice, and citation volume * Response counts These metrics can be grouped by dimensions including: * Date (day, week, month, quarter, year) * Prompt or prompt metadata * Persona * Tag * Platform * Competitor * Sub-brand * Source URL * Branded vs non-branded All results are **derived summaries**, not raw AI responses. *** ## When to use the Query API Use the Query API when you need: * Weekly or monthly reporting * Trend analysis over time * Brand and competitor visibility metrics * Aggregation by date, persona, tag, platform, or prompt * Data for dashboards (Looker, Power BI, Tableau) * Large batch metric pulls for automation or reporting The Query API is designed to answer questions like: “How is our AI visibility changing over time?”\ “How do we compare to competitors by topic or platform?” *** ## When not to use the Query API The Query API is not appropriate if you need: * Raw AI response text * Citation URLs or snippets * Per-response competitor sentiment or position * Full message-level audits or research For those use cases, use the **Responses API**, which exposes the underlying response records in full detail. *** ## Example query ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/query?fields=date_week,brand_presence_percentage,brand_sentiment_score" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` You can narrow results with `filters` (pre-aggregation, on dimensions) and `having` (post-aggregation, on metrics): ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/query?fields=date_week,ai_platform,brand_presence_percentage&filters=ai_platform:ChatGPT|Claude&having=brand_presence_percentage:gt:0.1" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` Break responses out by the individual fan-out queries an AI engine ran, instead of by the prompt you submitted: ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/query?fields=query_fanouts,responses" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` Break the brand / competitor / other ownership split out across responses — the shape BI tools (Looker, Power BI, Tableau) typically chart: ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/query?fields=owner,responses" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` *** ## Two ways to query The Query API exposes two endpoints that share the same dimensions and metrics: * **`GET /v1/{brand_id}/query`** — URL-parameter form. Use it for simple pulls and BI integrations that prefer query strings. * **`POST /v2/query/{brand_id}`** — JSON-body form. Use it when you need post-aggregation thresholds (`HAVING`), negated filters, or period-over-period comparison in a single request. See the [Structured Query Endpoint](/api-reference/query/structured-query) reference. Both endpoints require an API key with access to the target brand; the `POST /v2` endpoint additionally requires the **Query** scope on the key. *** ## Fields reference Specify fields in the `fields=` array to control what is returned. **Dimensions** determine how metrics are grouped — querying a dimension alone returns its unique values. **Metrics** are numeric measures — querying a metric alone returns its overall aggregate across all data. ### Dimensions | Field | Type | Description | Constraints | Prompt relationship | | ----------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | | `prompt_id` | Number | Unique identifier for the prompt | — | — | | `prompt` | String | Full text of the prompt submitted to the AI platform | — | — | | `date_month` | String | Month responses were collected, truncated to the first day of the month. Use for monthly trend reporting. | Last 90 days only | Many to many | | `date_week` | String | Calendar week responses were collected, truncated to the start of the week. Use for weekly trend reporting. | Last 90 days only. Recommend keeping date filters week-aligned. | Many to many | | `date` | String | Specific date responses were collected. Use for daily granularity. | Last 90 days only | Many to many | | `source_url` | String | Full URL of a citation source found in AI responses. Use to analyze which web properties appear most in AI answers. | — | Many to many | | `domain` | String | Registered domain of a citation source (e.g. `example.com`). Use to roll `source_url` data up to the domain level. | — | Many to many | | `owner` | String (Enum) | Ownership classification of a citation's domain. Values: `brand` (the tracked brand), `competitor` (a configured competitor), `other` (everything else). Use to chart the brand vs. competitor vs. third-party split. | Not filterable | Many to many | | `source_type` | String (Enum) | Ownership classification of a citation source. Values: `brand`, `competitor`, `other` (third-party in the Scrunch UI). Equivalent to `owner` and retained for backward compatibility — new integrations should prefer `owner`. | — | Many to many | | `source_domain` | String | Host of a citation source, lowercased and `www`-stripped (for example, `nytimes.com`). Use to group citations by publisher rather than by individual URL. | Computed on the raw query path — cannot be combined with citation metrics (use `domain` for that) and is not filterable. | Many to many | | `source_topic` | String | Topic tags assigned to a cited source's domain in your Scrunch brand configuration. Use to break citation metrics down by the subject areas of the pages that cite you (for example, "Product reviews" vs. "How-to guides"). Sources with no configured topics fall into an explicit `Untagged` bucket rather than being dropped. | Source-grain breakdown — only valid alongside citation metrics. Not filterable. List-valued: a source with multiple topics contributes one row per topic, so additive citation metrics (`citation_count`, `citation_unique_domains`) can double-count across a source's topics; rate metrics (`citation_rate`, mention rates) are unaffected. | Many to many | | `persona_id` | Number | Unique identifier for the persona associated with the prompt | — | One to many | | `persona_name` | String | Name of the persona associated with the prompt. Personas represent audience segments or geographic configurations. | — | One to many | | `competitor_id` | Number | Unique identifier for a competitor tracked in your Scrunch brand configuration | — | Many to many | | `competitor_name` | String | Name of the competitor. Use alongside competitor metrics to analyze individual competitor visibility. | — | Many to many | | `sub_brand_id` | Number | Unique identifier for a sub-brand tracked in your Scrunch brand configuration. Use alongside sub-brand metrics to analyze a specific product line, region, or division. | — | Many to many | | `ai_platform` | String (Enum) | AI platform that generated the response. Values: `chatgpt`, `perplexity`, `google_ai_overviews`, `meta`, `claude` | — | Many to many | | `tag` | String | User-defined tag attached to prompts in the Scrunch UI. Use to group and filter by custom categories. | — | Many to many | | `branded` | Boolean | Whether the prompt includes the brand name or an alternate brand name. Use to compare branded vs. unbranded query performance. | — | One to many | | `stage` | String | Stage of the customer journey the prompt is mapped to. Values are resolved from your brand's configured stages, so they vary per brand. Default sets: intent — `Advice`, `Awareness`, `Evaluation`, `Comparison`, `Other`; funnel — `Awareness`, `Consideration`, `Conversion`, `Loyalty`, `Other`. Brands that rename or add stages return those custom names. Filter values pass through verbatim — a value that doesn't match any of the brand's stages matches zero rows rather than erroring. | — | One to many | | `prompt_topic` | String | Key topic extracted from or assigned to the prompt. Use to group performance by topic area. | — | Many to many | | `country` | String | 2-letter ISO country code for which the response was retrieved, based on the persona or brand default configuration. | — | One to many | | `position_bucket` | String (Enum) | Where your brand appears inside a response when it is mentioned. Values: `top`, `middle`, `bottom`. Use to break mentions out by prominence — for example, to see what share of mentions land in the top of the answer. | Conditional dimension: rows where the brand is not mentioned are excluded from the breakdown. See [Breaking mentions down by a conditional dimension](#breaking-mentions-down-by-a-conditional-dimension). | Many to many | | `sentiment_band` | String (Enum) | How your brand is talked about inside a response when it is mentioned. Values: `positive`, `mixed`, `negative`, `none`. Use to break mentions out by tone — for example, to see what share of mentions are positive on each platform. | Conditional dimension: rows where the brand is not mentioned are excluded from the breakdown. See [Breaking mentions down by a conditional dimension](#breaking-mentions-down-by-a-conditional-dimension). | Many to many | | `rank` | Number | First-occurrence rank of the entity inside a response, where `1` is the first mention. Use to chart the rank distribution — for example, to see what share of mentions land at `#1` vs `#2` vs `#3`. | Conditional dimension: rows where the entity is not ranked (not mentioned) are excluded from the breakdown. See [Breaking mentions down by a conditional dimension](#breaking-mentions-down-by-a-conditional-dimension). | Many to many | | `query_fanouts` | String | Individual search query an AI engine generated internally during query fan-out. Each row in the response represents one fan-out query; observations without a fan-out yield zero rows for this dimension. Use to break metrics down by the underlying searches an AI platform actually ran. | Not filterable. Forces the raw query path, which can be slower than other dimensions. | Many to many | ### Metrics | Field | Type | Description | Aggregation | Constraints | | -------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `responses` | Number | Total number of AI responses collected for the selected dimensions. The base volume metric. | Count | — | | `unique_prompts` | Number | Distinct count of prompt variants that produced responses in the selected window. A prompt expands into one variant per platform × persona × geography × language × scenario combination, and variants are what Scrunch actually monitors — so this is what the Scrunch dashboard's "Prompts" tile reports. Use to size the underlying variant set behind any aggregate. | Distinct count | — | | `brand_presence_percentage` | Number | Percentage of responses in which your brand was mentioned. The primary measure of AI visibility. | Average | — | | `brand_unique_prompts` | Number | Distinct count of prompt variants where your brand was mentioned in at least one response. Variant-grain, matching `unique_prompts`. | Distinct count | — | | `brand_unique_responses` | Number | Distinct count of responses that mentioned your brand. | Distinct count | — | | `brand_share_of_voice` | Number | Your brand's share of mentions across the full competitive set. Computed as your brand's mention responses divided by the total mention responses for your brand plus all active competitors. Across a given slice, `brand_share_of_voice` plus the sum of `competitor_share_of_voice` for every competitor equals 1. Use to compare visibility on a normalized scale that ignores prompts where nobody was mentioned. | Ratio | Range: 0–1. The denominator always reflects the full brand-plus-competitors set, even if you filter to specific competitors. | | `brand_position_score` | Number | Weighted score (0–100) reflecting how prominently your brand appears across all responses. Derived from the distribution of Top, Middle, and Bottom positions — higher scores indicate more top-of-response appearances. **Note:** the Scrunch dashboard displays the raw share of Top-position responses; this score is a continuous aggregate and will differ from that figure. | Average | Range: 0–100 | | `brand_sentiment_score` | Number | Weighted score (0–100) reflecting overall sentiment toward your brand across all responses. Derived from the distribution of Positive, Mixed, Negative, and None sentiments — higher scores indicate a more positive distribution. **Note:** the Scrunch dashboard displays the raw share of Positive-sentiment responses; this score is a continuous aggregate and will differ from that figure. | Average | Range: 0–100 | | `brand_avg_rank` | Number | Average first-occurrence rank of your brand among same-type entities mentioned in a response, where `1` is the first mention. **Lower is better.** Only responses in which your brand was ranked contribute to the average — responses where your brand was not mentioned are skipped, so this metric measures positioning among ranked appearances only. Pair with `brand_presence_percentage` to see how often your brand shows up at all. | Average | Starts at 1. Computed over ranked appearances only. | | `competitor_presence_percentage` | Number | Percentage of responses in which the competitor was mentioned. | Average | Must be used with `competitor_id` or `competitor_name` (or both) | | `competitor_position_score` | Number | Weighted score (0–100) reflecting how prominently the competitor appears across all responses. Derived from the distribution of Top, Middle, and Bottom positions — see note on `brand_position_score` regarding differences from dashboard figures. | Average | Range: 0–100. Must be used with `competitor_id` or `competitor_name` (or both) | | `competitor_sentiment_score` | Number | Weighted score (0–100) reflecting overall sentiment toward the competitor across all responses. Derived from the distribution of Positive, Mixed, Negative, and None sentiments — see note on `brand_sentiment_score` regarding differences from dashboard figures. | Average | Range: 0–100. Must be used with `competitor_id` or `competitor_name` (or both) | | `competitor_avg_rank` | Number | Average first-occurrence rank of the competitor among same-type entities mentioned in a response, where `1` is the first mention. **Lower is better.** Only responses in which the competitor was ranked contribute to the average; responses where the competitor was not mentioned are skipped. Pair with `competitor_presence_percentage` to see how often the competitor shows up at all. | Average | Starts at 1. Computed over ranked appearances only. Must be used with `competitor_id` or `competitor_name` (or both) | | `competitor_unique_prompts` | Number | Distinct count of prompt variants where the competitor was mentioned in at least one response. Variant-grain, matching `unique_prompts`. | Distinct count | Must be used with `competitor_id` or `competitor_name` (or both) | | `competitor_unique_responses` | Number | Distinct count of responses that mentioned the competitor. | Distinct count | Must be used with `competitor_id` or `competitor_name` (or both) | | `competitor_share_of_voice` | Number | The competitor's share of mentions across the full competitive set. Computed as the competitor's mention responses divided by the total mention responses for your brand plus all active competitors. Pair with `competitor_id` or `competitor_name` for a per-competitor breakdown; without that dimension the value aggregates every competitor. The denominator stays fixed to the full set, so filtering competitor rows does not rescale the share. | Ratio | Range: 0–1. Must be used with `competitor_id` or `competitor_name` (or both) for per-competitor values. | | `sub_brand_presence_percentage` | Number | Percentage of responses in which the sub-brand was mentioned. Use to measure AI visibility for a specific product line, region, or division. | Average | Pair with `sub_brand_id` to break out by sub-brand, or filter `sub_brand_id` to isolate one | | `sub_brand_position_score` | Number | Weighted score (0–100) reflecting how prominently the sub-brand appears across all responses. Derived from the distribution of Top, Middle, and Bottom positions — see note on `brand_position_score` regarding differences from dashboard figures. | Average | Range: 0–100 | | `sub_brand_sentiment_score` | Number | Weighted score (0–100) reflecting overall sentiment toward the sub-brand across all responses. Derived from the distribution of Positive, Mixed, Negative, and None sentiments — see note on `brand_sentiment_score` regarding differences from dashboard figures. | Average | Range: 0–100 | | `sub_brand_unique_prompts` | Number | Distinct count of prompt variants where the sub-brand was mentioned in at least one response. Variant-grain, matching `unique_prompts`. | Distinct count | — | | `sub_brand_unique_responses` | Number | Distinct count of responses that mentioned the sub-brand. | Distinct count | — | | `sub_brand_share_of_voice` | Number | The aggregate share of mentions across the sub-brands you track under your brand. Computed as present `(sub_brand, response)` pairs over the total present pairs across all tracked sub-brands, so the values across a sub-brand set sum to 1. Use to gauge how attention is distributed across your own product lines, regions, or other sub-brand groupings. The denominator reflects the full tracked sub-brand set and does not shrink when you filter to a subset. | Ratio | Range: 0–1. Not compatible with the `tag` or `prompt_topic` breakdown dimensions (mirrors `brand_share_of_voice` / `competitor_share_of_voice`). | | `market_presence_percentage` | Number | Share of responses that mention **any** tracked entity — your brand or any active competitor. Note: this is response-level coverage, not the sum of per-entity mention rates. Use as the pooled "All (brands & competitors)" mention rate. | Average | Range: 0–1. Cannot be combined with brand, competitor, or sub-brand mention metrics in the same request, or with breakdowns scoped to a single entity (`competitor_id`, `competitor_name`, `sub_brand_id`). | | `market_position_score` | Number | Volume-weighted position score (0–100) pooled across every tracked entity. Each entity-mention contributes once, so this reconciles with per-entity `brand_position_score` / `competitor_position_score` weighted by mention volume. | Average | Range: 0–100. Same compatibility constraints as `market_presence_percentage`. | | `market_sentiment_score` | Number | Volume-weighted sentiment score (0–100) pooled across every tracked entity. Reconciles with per-entity sentiment scores weighted by mention volume. | Average | Range: 0–100. Same compatibility constraints as `market_presence_percentage`. | | `market_avg_rank` | Number | Volume-weighted average first-occurrence rank pooled across every tracked entity. **Lower is better.** Each ranked entity-mention contributes once; unranked rows are skipped. | Average | Starts at 1. Same compatibility constraints as `market_presence_percentage`. | | `citation_rate` | Number | Share of all responses in the slice that include at least one citation, regardless of who owns it. The denominator is every response in the slice. | Average | Range: 0–1 | | `brand_citation_rate` | Number | Share of all responses in the slice that cite at least one brand-owned domain. The denominator is every response in the slice, matching `brand_presence_percentage` semantics for citations. | Average | Range: 0–1 | | `competitor_citation_rate` | Number | Share of all responses in the slice that cite at least one competitor-owned domain. | Average | Range: 0–1. Cannot be combined with `competitor_id` / `competitor_name` (HTTP 400) — scope to specific competitors with the `cited_competitor_name` filter. | | `brand_citation_share_of_voice` | Number | Of responses that cite anything, the share that cite at least one brand-owned domain. The denominator is responses with at least one citation — use this to ask "when the AI cites sources, how often is it citing us?" | Ratio | Range: 0–1 | | `competitor_citation_share_of_voice` | Number | Of responses that cite anything, the share that cite at least one competitor-owned domain. | Ratio | Range: 0–1. Cannot be combined with `competitor_id` / `competitor_name` (HTTP 400) — scope with the `cited_competitor_name` filter. | | `citation_count` | Number | Total citation occurrences across responses in the slice. A response that cites three URLs contributes three. Entity-agnostic — counts every citation regardless of owner. | Sum | — | | `brand_citation_count` | Number | Total citation occurrences that resolve to a brand-owned domain. | Sum | — | | `competitor_citation_count` | Number | Total citation occurrences that resolve to a competitor-owned domain. | Sum | Cannot be combined with `competitor_id` / `competitor_name` (HTTP 400) — scope with the `cited_competitor_name` filter. | | `citation_unique_responses` | Number | Distinct count of responses that contain at least one citation. | Distinct count | — | | `brand_citation_unique_responses` | Number | Distinct count of responses that cite at least one brand-owned domain. | Distinct count | — | | `competitor_citation_unique_responses` | Number | Distinct count of responses that cite at least one competitor-owned domain. | Distinct count | Cannot be combined with `competitor_id` / `competitor_name` (HTTP 400) — scope with the `cited_competitor_name` filter. | | `citation_unique_domains` | Number | Distinct count of citation hosts (`www`-stripped) across responses in the slice. | Distinct count | — | | `brand_citation_unique_domains` | Number | Distinct count of brand-owned citation hosts (`www`-stripped). | Distinct count | — | | `competitor_citation_unique_domains` | Number | Distinct count of competitor-owned citation hosts (`www`-stripped). | Distinct count | Cannot be combined with `competitor_id` / `competitor_name` (HTTP 400) — scope with the `cited_competitor_name` filter. | | `sub_brand_citation_rate` | Number | Share of responses (0–1) that cite a source owned by the sub-brand. Use to measure how often AI grounds answers in your sub-brand's own web properties. | Average | Pair with `sub_brand_id` for per-sub-brand values (recommended — without it the value aggregates across all tracked sub-brands). Requires sub-brands to be configured for the brand. | | `sub_brand_citation_share_of_voice` | Number | Of responses that cite any source, the share (0–1) that cite a sub-brand-owned source. Use to compare a sub-brand's citation footprint against all cited domains. | Ratio | Pair with `sub_brand_id` for per-sub-brand values. | | `sub_brand_citation_count` | Number | Total citation occurrences across responses where the cited domain is owned by the sub-brand. | Count | Pair with `sub_brand_id` for per-sub-brand values. | | `sub_brand_citation_unique_responses` | Number | Distinct count of responses that include at least one citation to a sub-brand-owned source. | Distinct count | Pair with `sub_brand_id` for per-sub-brand values. | | `sub_brand_citation_unique_domains` | Number | Distinct count of sub-brand-owned domains (www-stripped) cited across responses. | Distinct count | Pair with `sub_brand_id` for per-sub-brand values. | | `brand_citation_mention_rate` | Number | Share of distinct cited URLs where your brand is named **in the content of the cited page itself** — not in the AI response text. Use to prioritize third-party outreach: which publishers already talk about you when the AI cites them. Distinct from `brand_presence_percentage` (which measures the AI response) and `brand_citation_rate` (which measures whether a brand-owned domain was cited). | Ratio | Range: 0–1. Computes on the source-grain path (forced): at aggregate grain and by `domain` it is a continuous rate; by `source_url` it collapses to a Yes/No (0 or 1) per URL. Cannot be combined with `competitor_id` / `competitor_name`. | | `competitor_citation_mention_rate` | Number | Share of distinct cited URLs where a competitor is named in the content of the cited page. Pair with `cited_competitor_name` (as a filter, breakdown, or both) to scope to a specific competitor or list the top mentioned competitors per source; without it, the metric covers all active competitors. | Ratio | Range: 0–1. Computes on the source-grain path (forced). To scope to specific competitors use the `cited_competitor_name` filter — combining with `competitor_id` / `competitor_name` returns HTTP 400. | | `weighted_index` | Number | **Influence Score.** Per-source ranking metric that combines how often a cited source appears with how many distinct prompts cite it. Higher scores indicate sources that both show up often and cover a broad range of prompts — the sources most worth prioritizing for outreach. Entity-agnostic (no brand/competitor variant); ranks every cited source in the slice. | Aggregate (per source) | **Requires a `domain` or `source_url` breakdown** — Influence Score only makes sense when one row equals one cited source. Coarser breakdowns (`owner`, `citation_segment`, `source_topic`) collapse many sources into a row and inflate the score, and are rejected with HTTP 400. Add `domain` or `source_url` to `fields`, or drop the metric. | | `cross_grain_presence_percentage` | Number | Cross-grain pooled presence rate — a single line that counts a response as "present" if any selected entity across both the brand grain (your brand plus selected competitors) *and* the sub-brand grain (selected sub-brands) appeared. Use to plot brand + sub-brand visibility as one combined line without double-counting a response that mentions entities on both grains. | Ratio | Range: 0–1. Presence-only — no position, sentiment, rank, or share-of-voice variant. See [Cross-grain pooled presence](#cross-grain-pooled-presence). | Citation metrics are computed on the staging source path. To break citations down by source, pair them with the `domain`, `source_url`, `owner`, `cited_competitor_name`, `citation_segment`, or `source_topic` dimensions — these activate the source-grain breakdown. You can also break citation metrics down by `prompt` (on its own or combined with a source-grain dimension) to see per-prompt citation rates. Mixing citation fields with high-cardinality dimensions can be slower than mention-only queries; keep date windows and field lists tight. **Pooled "All (brands & competitors)" metrics.** The `market_*` metrics roll mention, position, sentiment, and rank up across your brand and every active competitor in a single volume-weighted average. Use them to track the overall AI conversation about your category — not the sum of per-entity rates. They run as their own query path, so they cannot be mixed with brand, competitor, or sub-brand metrics in the same request; pull them on their own and combine the series downstream. Citation metrics cannot be combined with fields that force the raw query path — `competitor_id`, `competitor_name`, the competitor mention metrics, `ai_platform_search_enabled`, or `source_domain` — such requests return `HTTP 400`. To scope competitor citation metrics to specific competitors, use the `cited_competitor_name` filter; to break citations down by publisher, use `domain` instead of `source_domain`. The `prompt` dimension is supported: combining it with a citation metric (optionally alongside a source-grain dimension such as `domain` or `source_url`) returns the per-prompt citation rate. **Active-entity scope.** Sub-brand metrics, the `sub_brand_id` breakdown, competitor citation metrics, and the `cited_competitor_name` filter and breakdown only count rows tied to currently active sub-brands and competitors. Archived sub-brands (including those whose parent competitor is no longer active) and deactivated competitors are excluded from numerators, share-of-voice denominators, and breakdown values. Re-activate the entity in your Scrunch brand configuration to bring its history back into results. #### Example: citation metrics ```bash theme={null} # Weekly brand citation rate and share of voice on ChatGPT curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=date_week,brand_citation_rate,brand_citation_share_of_voice&filters=ai_platform:ChatGPT" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` ```bash theme={null} # Top citation domains, ranked by occurrence curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=domain,citation_count,citation_unique_responses&having=citation_count:gte:5" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` #### Example: Influence Score for outreach prioritization Rank cited domains by Influence Score alongside the share of pages that already mention your brand — a shortlist of high-influence sources you don't yet appear on: ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=domain,weighted_index,brand_citation_mention_rate&having=weighted_index:gte:1" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` #### Example: citations broken down by domain topic Break down citation volume by the topic tags configured for each cited source's domain. Untagged sources appear in an explicit `Untagged` bucket: ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=source_topic,citation_unique_domains,citation_count" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` #### Example: pooled market metrics ```bash theme={null} # Weekly pooled mention rate and position score across your brand + all competitors curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=date_week,market_presence_percentage,market_position_score" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` #### Example: sub-brand citation rate by platform Break down how often each AI platform cites a specific sub-brand's owned domains: ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=ai_platform,sub_brand_id,sub_brand_citation_rate&filters=sub_brand_id:$SUB_BRAND_ID" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` *** ## Cross-grain pooled presence `cross_grain_presence_percentage` pools presence across the **brand grain** (your brand plus selected competitors) and the **sub-brand grain** (selected sub-brands) into one presence rate. A response counts as present if *any* selected entity on *either* grain appeared, so a response that mentions both a brand-grain entity and a sub-brand-grain entity is counted once — not twice. Use it when you want to chart brand + sub-brand visibility as a single combined series (for example, "Own brand + all sub-brands" or "Own brand + one sub-brand + one competitor") without the double-counting you'd get from summing the per-grain rates. ### Selecting which entities join the pool By default the pool includes your own brand plus every active competitor and every active sub-brand. Narrow either grain with a positive filter on that grain's identity field: * `filters=competitor_name:` — narrows the competitor branch of the brand grain. Your own brand always stays in the pool. * `filters=sub_brand_id:` — narrows the sub-brand grain to the named sub-brand(s). * `filters=ownership:competitor` — signals "include the competitor branch" when you want all active competitors in the pool but have no specific names to list. Without either this filter or a `competitor_name` list, the pool drops the competitor branch entirely and uses your own brand alone on the brand grain. Multiple positive values on the same identity field are combined as `IN (...)` — the pool is the union of the named entities, matching what an Explorer multi-select produces. Negated identity filters (`competitor_name:!`, `sub_brand_id:!`) are rejected with `HTTP 400`. ### Supported breakdowns Cross-grain pooling is presence-only, so it accepts only the non-conditional lens dimensions: `date`, `date_week`, `date_month`, `date_quarter`, `date_year`, `ai_platform`, `stage`, `persona_name`, `persona_id`, `country`, `branded`, `prompt_id`. Entity-identity breakdowns (`competitor_id`, `competitor_name`, `sub_brand_id`) and source-grain dimensions (`domain`, `source_url`, `owner`, `source_domain`) are not supported — the pooled series has no per-entity split. Position, sentiment, rank, and share-of-voice have no cross-grain analogue and are not available either. ### Example Weekly combined presence for your brand, a chosen competitor, and one sub-brand on ChatGPT: ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=date_week,cross_grain_presence_percentage&filters=competitor_name:Acme&filters=sub_brand_id:17&filters=ai_platform:ChatGPT" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` Weekly combined presence for your brand plus every active sub-brand (no competitor leg): ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=date_week,cross_grain_presence_percentage" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` Only active competitors and sub-brands contribute to the pool. Archived competitors and sub-brands (including those whose parent competitor is no longer active) are excluded from the numerator, so re-activate them in your brand configuration to bring their history back in. *** ## Filtering results The Query API supports two filter parameters that narrow what is returned. Both can be combined in the same request and both can be repeated to apply multiple filters (combined with AND). ### Dimension filters (`filters`) Use `filters` to narrow rows **before** aggregation runs. Each filter takes the form `field:value`. Combine multiple values with `|` for an `IN` match, and prefix the value with `!` to negate. ```bash theme={null} # Only ChatGPT and Claude, branded prompts only curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=date_week,brand_presence_percentage&filters=ai_platform:ChatGPT|Claude&filters=branded:true" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` ```bash theme={null} # Exclude a specific competitor curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=competitor_name,competitor_presence_percentage&filters=competitor_id:!42" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` ```bash theme={null} # Weekly sentiment for a specific sub-brand, broken out by prompt topic curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=date_week,prompt_topic,sub_brand_sentiment_score&filters=sub_brand_id:17" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` **Filterable dimensions:** `prompt_id`, `persona_id`, `persona_name`, `ai_platform`, `ai_platform_search_enabled`, `tag`, `competitor_id`, `competitor_name`, `sub_brand_id`, `branded`, `stage`, `prompt_topic`, `country`, `position_bucket`, `sentiment_band`, `rank`, `date`, `date_week`, `date_month`, `date_quarter`, `date_year`. `rank` values must be positive integers (`1`, `2`, …); non-numeric values return `HTTP 400`. `source_url`, `domain`, `owner`, `source_domain`, `source_topic`, `prompt`, and `query_fanouts` are not filterable. ### Metric filters (`having`) Use `having` to filter on **aggregated** metric values after `GROUP BY` runs. Each entry takes the form `metric:operator:value`. | Operator | Meaning | | -------- | --------------------- | | `gt` | Greater than | | `gte` | Greater than or equal | | `lt` | Less than | | `lte` | Less than or equal | | `eq` | Equal | | `neq` | Not equal | ```bash theme={null} # Weeks where presence is above 10% and at least 50 responses were collected curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=date_week,brand_presence_percentage,responses&having=brand_presence_percentage:gt:0.1&having=responses:gte:50" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` The metric you reference in `having` must also appear in `fields`. *** ## Breaking mentions down by a conditional dimension `position_bucket`, `sentiment_band`, and `rank` are **conditional dimensions** — they describe how an entity appeared in a response, so they only exist on responses where that entity is actually mentioned (and, for `rank`, ranked): * `position_bucket`: `top`, `middle`, `bottom` * `sentiment_band`: `positive`, `mixed`, `negative`, `none` * `rank`: positive integers (`1`, `2`, …), where `1` is the first mention When you group by any of these, responses where the entity is not mentioned (or, for `rank`, not ranked) are excluded from the breakdown — there is no "not mentioned" or "rank 0" row. Alongside a presence metric, each row reports that bucket's **share of mentions**: the buckets within a group sum to 1.0 (100% of mentioned responses), not to the overall mention rate. To relate the shares back to overall visibility, run a second query without the conditional dimension or multiply each share by the overall presence metric. The conditional dimension follows the **entity scope of the metric** it is paired with: * Pair with `brand_*` mention metrics to break out your brand's position, sentiment, or rank distribution. * Pair with `competitor_*` mention metrics (plus a `competitor_id` / `competitor_name` filter) to break out a competitor's distribution. * Pair with `market_*` mention metrics to break out the pooled distribution across every tracked entity. ### Position breakdown ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=position_bucket,brand_presence_percentage" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` ```json theme={null} [ { "position_bucket": "top", "brand_presence_percentage": 0.58 }, { "position_bucket": "middle", "brand_presence_percentage": 0.29 }, { "position_bucket": "bottom", "brand_presence_percentage": 0.13 } ] ``` Here 58% of the responses that mention your brand place it in the top of the answer. ### Rank distribution ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=rank,brand_presence_percentage" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` ```json theme={null} [ { "rank": 1, "brand_presence_percentage": 0.62 }, { "rank": 2, "brand_presence_percentage": 0.24 }, { "rank": 3, "brand_presence_percentage": 0.10 }, { "rank": 4, "brand_presence_percentage": 0.04 } ] ``` Of all responses that mention your brand, 62% list it first. Pair `rank` with a `competitor_*` mention metric (and a `competitor_id` filter) to chart the same distribution for a competitor, or with a `market_*` mention metric to chart the pooled distribution across every tracked entity. ### Crossing with non-conditional dimensions The same decomposition holds per group when you cross a conditional dimension with a non-conditional one — shares sum to 1.0 within each `ai_platform` below: ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=ai_platform,position_bucket,brand_presence_percentage" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` ### Filtering on a conditional dimension You can also use either dimension purely as a filter — for example, to restrict every other metric in a query to responses where the brand appears in the top of the answer, or only to positive mentions: ```bash theme={null} # Top-of-answer mentions only curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=ai_platform,responses&filters=position_bucket:top" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" # Positive mentions on ChatGPT only curl "https://api.scrunchai.com/v1/$BRAND_ID/query?fields=ai_platform,responses&filters=sentiment_band:positive&filters=ai_platform:ChatGPT" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` This behavior only applies when `position_bucket` or `sentiment_band` is in `fields`. For queries that do not group by either, `brand_presence_percentage` keeps its usual meaning — the share of all responses that mention the brand. A single query cannot mix a brand metric **and** a competitor metric **and** a conditional dimension — one breakdown column can only describe one entity's row. Such requests return `HTTP 400`; split them into separate queries. `having` on a presence metric is also rejected with `HTTP 400` when a conditional dimension is in `fields`; filter on a count metric such as `brand_unique_responses` instead. *** ## Date range and validation Use the `start_date` and `end_date` query parameters to scope a request to a specific window. Both are optional and accept the `YYYY-MM-DD` format. | Behavior | What happens | | -------------------------------------------------------------------- | -------------------------------------------------------- | | Both omitted | Returns the last 30 days, ending today (UTC). | | Only `start_date` set | `end_date` defaults to today (UTC). | | Only `end_date` set | `start_date` defaults to 30 days before `end_date`. | | Empty string (`?start_date=`) | Treated as missing. The default applies. | | Trailing or leading whitespace (`?start_date=2026-03-20%20`) | Trimmed before parsing. The cleaned value is used. | | Malformed value (`?start_date=2024-02-30` or `?start_date=tomorrow`) | Returns `HTTP 400` with the offending value in `detail`. | ### Example: valid request ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/query?start_date=2026-03-01&end_date=2026-03-31&fields=date_week,brand_presence_percentage" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` ### Example: invalid date returns 400 ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/query?start_date=2024-02-30" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` ```json theme={null} { "detail": "Invalid start_date '2024-02-30': expected YYYY-MM-DD" } ``` If you build query strings dynamically, prefer omitting `start_date` / `end_date` when you don't have a value rather than passing an empty string — the result is the same, but the intent is clearer. *** ## Cardinality and result size Because the Query API performs grouping dynamically, combining highly granular dimensions can significantly increase the number of rows returned. Examples of high-cardinality dimensions include: * ai\_platform * tag * prompt\_topic * competitor\_id * competitor\_name * source\_url * source\_domain * domain * source\_type * query\_fanouts Each additional high-cardinality field multiplies the number of possible result rows. Avoid combining multiple high-cardinality dimensions unless required, as this can produce very large result sets and slower queries. *** ## Limits and performance considerations * The Query API supports large batch pulls (up to tens of thousands of rows per request) * Results are pre-aggregated and optimized for analytics and BI ingestion * Query performance degrades as result cardinality increases For best performance, keep field selections focused and intentional. *** ## Best practices * Prefer date\_week or date\_month over daily granularity when possible * Run separate queries for different reporting needs and join downstream * Keep field lists small to control result size * Use brand-scoped API keys when embedding in client-facing dashboards * Treat Query API outputs as metrics tables, not raw data logs *** ## Relationship to the Responses API The Query API and Responses API are complementary: * Query API: fast, aggregated metrics for reporting and dashboards * Responses API: full-fidelity response text and citation data for deep analysis Most customers use the Query API for ongoing reporting and the Responses API selectively for audits, research, or investigation. Go to the Query API Quickstart → # Structured Query API: Multi-Metric JSON Endpoint Source: https://developers.scrunch.com/api-reference/query/structured-query POST brand-scoped JSON queries with dimensions, metrics, HAVING thresholds, negated filters, and prior-period or prior-year comparisons in one call. ## Overview The structured query endpoint accepts a JSON request body describing the dimensions, metrics, filters, and comparisons you want, and returns a columnar result. Use it when you need richer query shapes than the [GET query endpoint](/api-reference/query/overview) supports — for example, post-aggregation thresholds, negated filters, or period-over-period comparison in a single round trip. ```http theme={null} POST https://api.scrunchai.com/v2/query/{brand_id} ``` The structured endpoint and the `GET` endpoint share the same dimensions, metrics, and brand scoping. They differ in expressivity and request shape: the structured endpoint takes a JSON body and adds `having`, `negate`, and `comparison`. *** ## When to use Use the structured endpoint when you need to: * Filter on metric thresholds after aggregation (for example, only weeks with at least 10 responses). * Exclude a set of values rather than include them (`negate: true`). * Pull a current-period result and a prior-period result in one request, aligned for charting. * Submit complex filter combinations that are awkward to encode in URL parameters. For straightforward dimension-and-metric pulls, the [GET query endpoint](/api-reference/query/overview) remains the simpler choice. *** ## Authentication Authenticate with a Bearer API key. The key must include the **Query** scope and have access to the target brand. See [Provision an API Key](/getting-started/authentication). ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/query/$SCRUNCH_BRAND_ID" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d @query.json ``` *** ## Request body | Field | Type | Required | Description | | ------------ | --------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------- | | `fields` | `string[]` | Yes | Dimensions and metrics to return. 1–32 entries. See [Fields reference](/api-reference/query/overview#fields-reference). | | `start_date` | `string` (YYYY-MM-DD) | No | Inclusive start. Defaults to 30 days ago. Required when `comparison` is set. | | `end_date` | `string` (YYYY-MM-DD) | No | Inclusive end. Defaults to today. Required when `comparison` is set. | | `filters` | `DimensionFilter[]` | No | Pre-aggregation `WHERE` filters on dimensions. Up to 25 entries. | | `having` | `HavingFilter[]` | No | Post-aggregation `HAVING` filters on metrics. Up to 10 entries. | | `comparison` | `Comparison` | No | Period-over-period comparison configuration. | | `limit` | `integer` | No | Row cap. Default `50000`, maximum `90000`. | | `offset` | `integer` | No | Row offset for pagination. Default `0`. | ### DimensionFilter ```json theme={null} { "field": "ai_platform", "values": ["ChatGPT"], "negate": false } ``` | Field | Type | Description | | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `field` | string | A filterable dimension. `prompt` is not filterable. | | `values` | array | One or more values to match. Up to 1000 entries. Values are coerced to the dimension's type — booleans accept `true`/`false`, `1`/`0`, `"true"`/`"false"`, `"yes"`/`"no"`; integer dimensions accept numeric strings. Mismatched types return HTTP `422`. | | `negate` | boolean | When `true`, excludes rows that match. With `match: "all"`, this excludes prompts carrying every specified value; it does not exclude prompts carrying only some of them. Default `false`. | | `match` | enum | How multiple `values` combine. `"any"` (default) matches prompts carrying at least one value (OR). `"all"` matches only prompts carrying every value (AND). Only supported on the array-valued prompt dimensions `tag` and `prompt_topic`; sending `"all"` on any other field returns HTTP `422`. | #### Match modes By default, multi-value filters combine with OR — a filter on `tag` with `["A", "B"]` returns prompts tagged **A or B**. This widens the result set as you add values. Set `match: "all"` on `tag` or `prompt_topic` to combine with AND instead — the filter then returns only prompts tagged **A and B**, narrowing the result set. Use this when a prompt can carry multiple tags or topics and you want to isolate the intersection (for example, product-level reporting that requires two tags at once). `match` only applies to `tag` and `prompt_topic`, which map each prompt to a set of values. Scalar dimensions like `ai_platform` or `country` reject `match: "all"` with HTTP `422` — a row has one platform, so AND across values would match nothing. Omit `match` (or send `"any"`) on scalar dimensions. ### HavingFilter ```json theme={null} { "metric": "responses", "operator": "gte", "value": 10 } ``` | Field | Type | Description | | ---------- | ------ | ----------------------------------------------------------------------- | | `metric` | string | A metric in `fields`. Referencing a metric not in `fields` is an error. | | `operator` | enum | One of `gt`, `gte`, `lt`, `lte`, `eq`, `neq`. | | `value` | number | The threshold. `inf` and `nan` are rejected. | ### Comparison ```json theme={null} { "mode": "prior_period" } ``` | Field | Type | Description | | ------ | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `mode` | enum | `prior_period` shifts back by the window length. `prior_year` shifts back by one calendar year (Feb 29 falls back to Feb 28 in non-leap years). | When `comparison` is set, `start_date` and `end_date` are required and the response includes a synthetic `period` dimension with values `current` and `prior`. Each period is capped at `limit / 2` rows so the merged result stays within `limit`. Prior-period dates are aligned to current-period bucket labels so the two series overlay on a chart. *** ## Response The response is columnar. ```jsonc theme={null} { "columns": [ { "name": "date_week", "kind": "dimension", "dtype": "date" }, { "name": "brand_presence_percentage", "kind": "metric", "dtype": "float" } ], "rows": [ ["2026-W14", 0.421], ["2026-W15", 0.478] ], "pagination": { "limit": 50000, "offset": 0 }, "compare_status": null } ``` | Field | Type | Description | | ------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `columns` | array | Column metadata in the same order as `rows`. `kind` is `dimension` or `metric`. `dtype` is one of `string`, `int`, `float`, `bool`, `date`. | | `rows` | array | Each row has one cell per column. | | `pagination.limit` | integer | The row cap clients should use for end-of-page detection. Echoes `limit` for non-comparison queries and for successful comparison queries (each period is capped at `limit / 2` rows, and the merged result never exceeds `limit`). When `compare_status` is `"current_only"`, returns `limit / 2` — the cap that was actually applied to the surviving current series. | | `pagination.offset` | integer | Echoes the requested offset. | | `compare_status` | `"current_only"` \| `null` | Set to `"current_only"` when `comparison` was requested but the prior-period query failed; the response then contains only the current series. `null` otherwise. | Date dimensions are formatted as labels: `date` → `YYYY-MM-DD`, `date_week` → ISO `YYYY-Www` (uses ISO week-numbering year, so dates near the year boundary group with their ISO week — for example, `2024-12-30` is `2025-W01`), `date_month` → `YYYY-MM`, `date_quarter` → `YYYY-Q#`, `date_year` → `YYYY`. *** ## Examples ### Multi-metric weekly trend with a platform filter ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/query/$SCRUNCH_BRAND_ID" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "start_date": "2026-04-01", "end_date": "2026-04-30", "fields": ["date_week", "brand_presence_percentage", "brand_unique_prompts"], "filters": [ { "field": "ai_platform", "values": ["ChatGPT"] } ] }' ``` ### Threshold the result with HAVING Return only weeks that received at least 10 responses. ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/query/$SCRUNCH_BRAND_ID" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "start_date": "2026-04-01", "end_date": "2026-04-30", "fields": ["date_week", "responses", "brand_presence_percentage"], "having": [ { "metric": "responses", "operator": "gte", "value": 10 } ] }' ``` ### Period-over-period comparison ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/query/$SCRUNCH_BRAND_ID" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "start_date": "2026-04-01", "end_date": "2026-04-30", "fields": ["date_week", "brand_presence_percentage"], "comparison": { "mode": "prior_period" } }' ``` The response prepends a `period` column. Prior dates are mapped to current-period labels so the series can be plotted on a single x-axis. ### Exclude specific prompts ```json theme={null} { "fields": ["prompt_topic", "responses"], "filters": [ { "field": "prompt_topic", "values": ["Pricing", "Support"], "negate": true } ] } ``` ### Match all tags (AND) instead of any (OR) Return only prompts carrying **both** tags. Without `match: "all"`, this filter returns prompts carrying **either** tag. ```json theme={null} { "fields": ["brand_presence_percentage"], "filters": [ { "field": "tag", "values": ["Enterprise", "Security"], "match": "all" } ] } ``` *** ## Limits | Limit | Value | | --------------------------- | ---------- | | Fields per request | 32 | | Filters per request | 25 | | HAVING clauses per request | 10 | | Values per filter | 1000 | | Rows per response (`limit`) | 90000 | | Default rows per response | 50000 | | Server-side execution time | 30 seconds | Requests that exceed these limits are rejected with HTTP `422`. *** ## Errors | Status | Cause | | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `401` | Missing or invalid API key. | | `403` | API key lacks the `query` scope or access to the brand. | | `400` | The field combination cannot be built into a single query — for example, citation metrics combined with raw-path-only fields, or a share-of-voice metric with an unsupported breakdown. Also returned for an unknown `citation_segment_id` filter value. | | `404` | Brand not found. | | `422` | Request body fails validation (for example, a non-filterable dimension in `filters`, a HAVING metric not in `fields`, `start_date` after `end_date`, a value that cannot be coerced to the dimension's type, a HAVING `value` of `inf` or `nan`, `match: "all"` on a dimension other than `tag` or `prompt_topic`, or a request that exceeds the size limits). | | `500` | Server error. When triggered by the prior-period query in a comparison request, the response succeeds with `compare_status: "current_only"` instead. | *** ## Related Field reference shared with the `GET` endpoint. First request walkthrough. # Responses API: Raw AI Answers and Citations Source: https://developers.scrunch.com/api-reference/responses/overview Retrieve every raw AI response Scrunch collects with full text, citations, sentiment, competitor evaluations, persona, and platform metadata. ## Overview The Responses API provides row-level access to the full AI responses captured by Scrunch. Each record represents a single AI-generated answer observed on a supported platform and includes the complete response text, citation metadata, and brand and competitor evaluations. This API is designed for teams that need maximum fidelity into how AI platforms answer questions about their category, brand, and competitors. Typical use cases include ETL pipelines, research workflows, full-text analysis, citation audits, internal tooling, and advanced modeling. *** ## What the Responses API includes Each response record may include: * Full AI response text (markdown) * Citations, including URL, domain, snippet, title, and source type * Brand presence, sentiment, and position * Competitor presence, sentiment, and position * Prompt metadata (persona, tags, key topics, stage) * Platform, country, and collection timestamp Each item corresponds to one AI response, not an aggregate or summary. *** ## When to use the Responses API Choose the Responses API if you need: * Per-response visibility instead of averages * The exact text produced by AI platforms * Citation-level analysis and influence modeling * Competitor comparisons within individual responses * Custom pipelines or internal UIs built on raw AI output * Daily or periodic ingestion jobs using high watermarks This API is intentionally verbose and optimized for depth and accuracy rather than aggregation. *** ## When not to use the Responses API The Responses API is not ideal if you only need: * Aggregated metrics (presence percentage, position score, sentiment score) * Lightweight dashboards or BI reporting * Trend analysis over time without response text For those use cases, the Query API is more efficient and better suited. *** ## Data mutability and re-evaluation Not all fields behave the same over time. Immutable fields: * response\_text * citations * created\_at These reflect exactly what was observed at the time the response was captured. Fields that may be re-evaluated: * stage, tags, key\_topics * brand\_present, brand\_sentiment, brand\_position * competitors evaluation fields These may change if prompt metadata is edited in the Scrunch UI or if brand configuration is updated and re-evaluation is requested. For ETL workflows, always deduplicate or upsert using the globally unique id. *** ## Request parameters All parameters are optional. | Parameter | Type | Description | Notes | | ------------ | ------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | | `platform` | String (Enum) | AI platform to retrieve responses for | Valid values: `chatgpt`, `claude`, `google_ai_overviews`, `perplexity`, `meta`, `google_ai_mode`, `google_gemini` | | `prompt_id` | Number | Specific prompt ID to retrieve responses for | | | `start_date` | Date (`YYYY-MM-DD`) | Start date of responses to retrieve | Inclusive | | `end_date` | Date (`YYYY-MM-DD`) | End date of responses to retrieve | Exclusive | | `limit` | Number | Maximum number of responses to return | Must be greater than 1, max 1000 | | `offset` | Number | Offset for pagination | Should be a multiple of `limit` | For incremental ingestion: 1. Pull responses using a date window 2. Store the `created_at` value from the latest record 3. Use that internally as a high watermark 4. Or load the previous UTC day after midnight to ensure completeness *** ## Denormalized response model Each API item represents a single response with related data embedded as arrays. * citations * tags * key\_topics * competitors The API does not fan out rows for many-to-many relationships. If you are building dimensional tables or star schemas, you will need to normalize these arrays downstream. This differs intentionally from the Query API, which performs aggregation and grouping. *** ## Response schema ### Collection Responses use Scrunch’s standard paginated collection format. | Field | Type | Description | Notes | | -------- | ------------ | -------------------------------------------------------------- | --------------------------------------------------- | | `total` | Number | Total number of responses available for the current parameters | | | `offset` | Number | Current offset retrieved | Add `limit` to this value to retrieve the next page | | `limit` | Number | Limit applied to the current request | | | `items` | `Response[]` | List of Response objects | See below | To retrieve the next page: ``` offset = offset + limit ``` For stable ETL jobs, ensure offset increments in multiples of `limit`. ### Response | Field | Type | Description | Notes | | --------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | `id` | Number | Unique ID for the response | Responses are immutable in normal operations — safe to deduplicate or upsert on `id` | | `created_at` | Timestamp (UTC) | Granular timestamp the response was collected at | | | `prompt_id` | Number | Unique ID for the prompt | Can be retrieved from the Prompts API | | `prompt` | String | Prompt text | | | `persona_id` | Number (Nullable) | Persona ID attached to the prompt | | | `persona_name` | String (Nullable) | Persona name attached to the prompt | | | `country` | String (Nullable) | 2-character ISO country code the response was retrieved for | | | `stage` | String | Stage of the customer journey the prompt is mapped to. Values are resolved from your brand's configured stages, so they vary per brand. Default sets: intent — `Advice`, `Awareness`, `Evaluation`, `Comparison`, `Other`; funnel — `Awareness`, `Consideration`, `Conversion`, `Loyalty`, `Other`. Brands that rename or add stages return those custom names. | | | `tags` | String\[] | Tags attached to the prompt | | | `key_topics` | String\[] | Key topics attached to the prompt | | | `platform` | String (Enum) | AI platform the response was retrieved from | See platform values under Request Parameters | | `brand_present` | Boolean | Whether the brand is present in the response | | | `brand_sentiment` | String (Enum) (Nullable) | Sentiment toward the brand | Null when brand not present. Values: `Positive`, `Mixed`, `Negative`, `None` | | `brand_position` | String (Enum) (Nullable) | Position of the brand within the response | Null when brand not present. Values: `Top`, `Middle`, `Bottom` | | `competitors_present` | String\[] | List of competitor names found in the response | | | `response_text` | String | Full AI-generated response text | Markdown format | | `citations` | `Citation[]` | Citations included in the response | See Citation below | | `competitors` | `CompetitorEvaluation[]` | Per-competitor evaluation data | Superset of the information in `competitors_present`. See CompetitorEvaluation below | ### Citation | Field | Type | Description | Notes | | ------------- | ----------------- | -------------------------------------- | ------------------------------------------------------------------------------------- | | `url` | String | URL of the citation | | | `title` | String (Nullable) | Title tag of the citation | Not exposed by all platforms | | `snippet` | String (Nullable) | Search engine snippet for the citation | Often but not always from the meta description tag. Not exposed by all platforms | | `source_type` | String (Enum) | Classification of the citation source | `Brand`, `Competitor`, `Other` — "Other" corresponds to third-party in the Scrunch UI | | `domain` | String | Domain name of the URL | Provided for convenience | ### CompetitorEvaluation | Field | Type | Description | Notes | | ----------- | ------------------------ | ------------------------------------------------- | ----------------------------------------------------------------------------- | | `name` | String | Name of the competitor | | | `id` | Number | Unique ID for the competitor | | | `present` | Boolean | Whether the competitor is present in the response | | | `position` | String (Enum) (Nullable) | Position of the competitor within the response | Null when `present` is false. Values: `Top`, `Middle`, `Bottom` | | `sentiment` | String (Enum) (Nullable) | Sentiment toward the competitor | Null when `present` is false. Values: `Positive`, `Mixed`, `Negative`, `None` | *** ## ETL recommended workflow 1. Start with `start_date` (UTC) 2. Pull responses in batches (`limit=1000`) 3. Store `created_at` from the last record 4. Use that as the new start date for your next batch 5. Deduplicate using `id` (globally unique) ## Typical downstream uses Customers commonly use the Responses API to: * Audit AI hallucinations or brand misrepresentation * Analyze which third-party sources influence AI answers * Train internal RAG or evaluation systems * Perform NLP or sentiment analysis across competitors * Build internal review tools for AI output quality * Support custom reporting or research workflows Responses API Quickstart → # Signals API: Detected changes in AI visibility Source: https://developers.scrunch.com/api-reference/signals/overview Query Scrunch's nightly detection sweep for statistically-tested level changes and trends in AI visibility metrics, with stable signal identity. ## Overview The Signals API exposes Scrunch's nightly detection sweep as a queryable feed. Each **signal** is a statistically-tested movement — a level change or trend — in one of your brand's AI visibility metrics on a specific slice of your data (a platform, topic, or the account as a whole). Use it to feed alerts into your own tools, drive weekly briefs, or automate follow-up on the same "what changed" events surfaced in the Scrunch dashboard. *** ## What the Signals API includes * Detected level changes and trends on core metrics (`presence_rate`, `position_top_rate`, `cited_domain_rate`) * A confidence tier for each signal (`high`, `confident`, `worth_a_look`, `provisional`), with noise-floor tiers available on request * Human-readable narrative: what happened, why it matters, and what to do * A **stable fingerprint** for each underlying issue — the same signal keeps its fingerprint across nightly re-detections, so reactions and downstream state survive * Reactions (`useful`, `not_useful`, `dismissed`, `actioned`) with optional free-text reasons, listable brand-wide for team-level reporting * Anchor dates (distinct detection days) for building date pickers and polling loops Signals are dedup-to-latest per identity: over a multi-day range you see one row per underlying issue, not one row per re-detection. *** ## When to use the Signals API Use the Signals API when you need to: * Post "what changed this week" summaries to Slack, email, or a stakeholder digest * Route detected drops on a specific platform, topic, or metric into an incident tracker * Export the team's reactions on signals for reporting or feedback loops * Build a custom alerting dashboard that mirrors the Scrunch Signals feed For ad-hoc "how is metric X trending" questions, use the [Query API](/api-reference/query/overview) — Signals only surfaces movements that pass detection thresholds. *** ## Endpoints | Method | Path | Purpose | | ------ | ------------------------------------------ | --------------------------------------------------- | | GET | `/{brand_id}/signals` | List detected signals with filters. | | GET | `/{brand_id}/signals/{signal_id}` | Get one signal with its full narrative. | | GET | `/{brand_id}/signals/anchors` | List recent detection dates that produced signals. | | GET | `/{brand_id}/signals/reactions` | List reactions across the brand's signals. | | PUT | `/{brand_id}/signals/{signal_id}/reaction` | Set (or replace) the caller's reaction on a signal. | | DELETE | `/{brand_id}/signals/{signal_id}/reaction` | Clear the caller's reaction. | All endpoints require a bearer token with the `query` scope. Reaction writes additionally require a **user token (JWT)** — API keys have no user identity to attribute a reaction to and receive `403`. See [Authentication](/getting-started/authentication). *** ## Filters The list endpoint accepts: | Filter | Description | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `scope` | Slice granularity: `account`, `account_platform`, `topic`, or `topic_platform`. | | `platform` | AI platform (e.g. `OpenAI`). Multi-platform signals carry the `(multi)` sentinel; the response `slice.platforms` lists the real platforms. | | `metric` | Metric the signal fired on (`presence_rate`, `position_top_rate`, `cited_domain_rate`). | | `alert_type` | `level_change` (step shift) or `trend` (sustained drift). | | `direction` | `up`, `down`, or `none`. | | `subject_kind` | `brand` or `competitor`. | | `tier` | Restrict to a single confidence tier. Omitting it returns the default user-facing tiers (`high`, `confident`, `worth_a_look`, `provisional`); pass an explicit tier to include noise-floor tiers (`low_confidence`, `underpowered`, `untested`). | | `anchor_from` / `anchor_to` | Inclusive `detected_for_date` bounds (`YYYY-MM-DD`). | | `mover_url` | Case-insensitive substring matched against the URLs in each signal's `url_movers` (per-URL citation movers, emitted for `cited_domain_rate` signals). Only signals with at least one matching mover URL are returned; signals without URL movers never match. `%` and `_` are matched literally. 1–2048 characters. | | `sort` | `score_desc` (default — engine priority), `delta_desc` (largest absolute change), or `detected_desc` (newest detection). | | `limit` / `offset` | Page size (default `50`, max `200`) and offset. | The reactions list endpoint supports `fingerprint` (all reactions on one signal identity) and `reaction` (all reactions of a given value). *** ## Example: list recent high-confidence signals ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/signals?tier=high&sort=detected_desc&limit=20" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` **Response:** ```json theme={null} { "total": 4, "offset": 0, "limit": 20, "items": [ { "id": 90211, "detected_for_date": "2026-07-14", "fingerprint": "b1e0c7a4f9e5...", "subject_kind": "brand", "alert_type": "level_change", "scope": "account_platform", "metric": "presence_rate", "platform": "OpenAI", "direction": "down", "tier": "high", "current_value": 0.31, "baseline_value": 0.47, "delta_absolute": -0.16, "score": 0.82, "narrative_what": "Brand presence on OpenAI dropped 16 pts week-over-week.", "narrative": { "what_happened": "Presence on OpenAI fell from 47% to 31% over the last 7 days.", "why_it_matters": "OpenAI drives the largest share of your tracked AI traffic.", "what_to_do": "Investigate top prompts where the brand disappeared and check citation coverage." }, "slice": { "platforms": ["OpenAI"], "topic_labels": [], "geo_country": null }, "window_current_start": "2026-07-08", "window_current_end": "2026-07-14", "baseline_definition": "Previous 28 days", "url_movers": [], "created_at": "2026-07-15T02:14:00Z" } ] } ``` *** ## Example: get one signal's full narrative ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/signals/90211" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` `getSignal` returns `404` for IDs that exist but aren't user-facing (non-fired detections or cluster-child rows) — the same population rule as the list endpoint. *** ## Example: react to a signal Reactions are keyed on the signal's stable `fingerprint`, so a thumbs-up survives the nightly re-detection of the same underlying issue. This call requires a **user token (JWT)**. ```bash theme={null} curl -X PUT \ "https://api.scrunchai.com/v1/1234/signals/90211/reaction" \ -H "Authorization: Bearer $SCRUNCH_USER_JWT" \ -H "Content-Type: application/json" \ -d '{ "reaction": "actioned", "reason": "Filed ticket ENG-4421." }' ``` ```json theme={null} { "user_id": 55, "insight_id": 90211, "fingerprint": "b1e0c7a4f9e5...", "reaction": "actioned", "reason": "Filed ticket ENG-4421.", "surface": "api", "created_at": "2026-07-15T09:02:11Z", "updated_at": "2026-07-15T09:02:11Z" } ``` Clear a reaction with `DELETE /v1/{brand_id}/signals/{signal_id}/reaction`. *** ## Example: list team reactions The reactions list is **brand-wide** — it returns every user's reactions, not just the caller's — so an integration can export the team's aggregate feedback. ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/signals/reactions?reaction=useful&limit=100" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` Filter by `fingerprint` to pull every reaction on one signal identity across re-detections. *** ## Example: poll for new detection dates ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/signals/anchors?limit=14" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` ```json theme={null} { "dates": ["2026-07-14", "2026-07-13", "2026-07-12"] } ``` Every returned date has at least one user-facing signal. Use it to drive a date picker or as a cheap check before pulling the full list. *** ## URL movers on citation signals For `cited_domain_rate` signals, each response includes a `url_movers` array — the per-URL citation movers behind the movement. Each mover carries: | Field | Description | | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | | `normalized_url` | Cited URL with scheme and tracking params stripped. | | `owner` | `brand` (your site) or `competitor`. | | `competitor_id` / `competitor_name` | Set on `competitor`-owned URLs. | | `current_responses` / `baseline_responses` | Distinct AI responses citing the URL in the current and baseline windows. | | `current_prompts` / `baseline_prompts` | Distinct prompts behind those responses. | | `contribution` | Exact share of the signal's metric delta attributed to the URL. Brand-owned URLs only; `null` on competitor entries and on older signals. | `url_movers` is empty for non-citation metrics and for signals detected before movers were recorded. ### Filter signals by mover URL Use `mover_url` to narrow the feed to signals whose citation movers touch a specific page or domain fragment. The match is a case-insensitive substring against each mover's `normalized_url`. ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/signals?metric=cited_domain_rate&mover_url=/pricing&limit=20" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` **Example mover on a returned signal:** ```json theme={null} { "normalized_url": "example.com/pricing", "owner": "brand", "competitor_id": null, "competitor_name": null, "current_responses": 42, "baseline_responses": 71, "current_prompts": 28, "baseline_prompts": 49, "contribution": -0.08 } ``` Signals without any URL movers never match `mover_url`, so combine it with `metric=cited_domain_rate` when you want a citation-focused feed. `%` and `_` in the input are matched literally. *** ## Signal identity and dedupe Every signal carries a `fingerprint` — a hash over its slice and metric — that stays stable across the nightly re-detection of the same underlying issue. Two implications: * **List responses dedupe to the latest detection.** Over a multi-day `anchor_from`/`anchor_to` window you see one row per fingerprint, not one per day. * **Reactions follow the fingerprint, not the row ID.** A `useful` set today still applies to tomorrow's re-detection of the same signal. Persist the `fingerprint` (not the numeric `id`) if you need to correlate signals across runs in your own system. *** ## Best practices * Poll `/signals/anchors` first to check whether a new detection day exists before pulling the full list. * Sort by `detected_desc` for "what's new" digests, `score_desc` for "what matters most", and `delta_desc` when ranking by raw movement. * Store the `fingerprint` alongside your internal record so reactions and follow-up state survive re-detections. * Use the reactions list to close the loop on "which alerts drove action" — filter by `reaction=actioned` for a running list of resolved signals. * For automated triage from an AI assistant, the same feed is available through the [Scrunch MCP server](/mcp/overview) via the `list_signals` and `get_signal` tools. # Site Audit API: Score pages for AI search readiness Source: https://developers.scrunch.com/api-reference/site-audit/overview Queue page audits for URLs on your brand's domain and fetch the AI search readiness checks, scores, and previews that power the Site Audit stage. ## Overview The Site Audit API runs Scrunch's AI search readiness audit against any URL on a brand's domain. Each audit fetches the page, runs the same checks that power the Site Audit stage of the [optimize-and-deploy pipeline](/api-reference/optimize-deploy), and returns a per-check result, an overall score, and a rendered preview of what AI crawlers see. Use it to audit pages on demand from your own automation — for example, after a publish, as part of a CI gate, or to backfill audits for a list of priority URLs. *** ## What the Site Audit API includes * Queue one or many URLs for audit in a single call * Audit status and timestamps (`pending`, `running`, `completed`, `failed`) * Per-check results for the AI search readiness suite (robots, rendering, schema, content quality, and more) * An overall audit score * An AI preview (markdown) showing what AI crawlers extract from the page * A visitor preview image for the rendered page * Filtering and pagination over the brand's audit history Results land in the Scrunch dashboard's Site Audit views and fire the `audit.completed` [webhook](/api-reference/webhooks/overview) on completion. *** ## When to use the Site Audit API Use the Site Audit API when you need to: * Trigger an audit immediately after publishing or updating a page * Re-audit a set of priority URLs on a schedule * Pull audit results into a custom dashboard or report * Programmatically gate a deploy on the audit outcome For audits across the brand's full sitemap, use the [Sitemap API](/api-reference/sitemap/overview) — every page in the sitemap already carries its most recent audit score. *** ## Endpoints | Method | Path | Purpose | | ------ | ----------------------------------------- | -------------------------------------------- | | POST | `/{brand_id}/page-audits` | Queue one or more URLs for audit. | | GET | `/{brand_id}/page-audits` | List audits in reverse chronological order. | | GET | `/{brand_id}/page-audits/{page_audit_id}` | Get a single audit, including check results. | `POST` requires a bearer token with `configure` scope. The `GET` endpoints require `query` scope. See [Authentication](/getting-started/authentication). URLs are normalized and deduplicated before being queued. URLs outside the brand's registered domains are rejected. *** ## Filters The list endpoint supports: | Filter | Description | | -------- | ----------------------------------------------------------- | | `status` | Restrict to `pending`, `running`, `completed`, or `failed`. | | `url` | Case-insensitive substring match on the audited URL. | | `limit` | Page size (default `100`). | | `offset` | Offset for pagination. | *** ## Example: queue audits ```bash theme={null} curl -X POST \ "https://api.scrunchai.com/v1/1234/page-audits" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "urls": [ "https://example.com/products/widgets", "https://example.com/blog/launch" ] }' ``` **Response:** ```json theme={null} [ { "url": "https://example.com/products/widgets", "page_audit_id": "01J9Z4K8R0G6M1Q3VN7N0H4T2A" }, { "url": "https://example.com/blog/launch", "page_audit_id": "01J9Z4K8R0G6M1Q3VN7N0H4T2B" } ] ``` Audits start `pending`. Poll the detail endpoint or subscribe to the `audit.completed` webhook to know when results are ready. *** ## Example: fetch an audit result ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/page-audits/01J9Z4K8R0G6M1Q3VN7N0H4T2A" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` A completed response carries the per-check results, an overall score, and previews: ```json theme={null} { "url": "https://example.com/products/widgets", "status": "completed", "result": { "version": 2, "checks": [ { "id": "robots_allows_ai", "passed": true, "score": 1.0 }, { "id": "renders_without_js", "passed": false, "score": 0.0 } ], "visitor_preview_image_url": "https://...", "ai_preview_markdown": "# Widgets\n\nOur flagship..." }, "created_at": "2026-06-05T14:02:00Z", "updated_at": "2026-06-05T14:02:41Z" } ``` While the audit is still in flight, `status` is `pending` or `running` and `result` is `null`. *** ## Example: list recent failed audits ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/page-audits?status=failed&limit=20" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` *** ## Limits and behavior * `POST` accepts up to 100 URLs per call. Submit larger batches across multiple requests. * Submissions are rate-limited at 60 audits per minute per brand. * URLs are normalized (trailing slash, casing) and deduplicated before queueing, so resubmitting the same URL in a batch returns a single ID. * Audits run asynchronously. Typical completion is under a minute; complex pages can take longer. * Audits older than the brand's retention window are pruned from the list endpoint. *** ## Best practices * Prefer the `audit.completed` [webhook](/api-reference/webhooks/overview) over polling — it fires the moment results are available. * Store `page_audit_id` alongside your internal record so you can correlate webhook deliveries back to the URL that triggered them. * Use the `url` filter on the list endpoint to find the latest audit for a specific page without scanning history. * For end-to-end "audit, optimize, deploy" automation, use the [optimize-and-deploy pipeline](/api-reference/optimize-deploy) instead of orchestrating these endpoints by hand. # Export Sitemap Pages Source: https://developers.scrunch.com/api-reference/sitemap/export-sitemap-pages /api-reference/openapi.json get /{brand_id}/sitemap/export Download every page matching the supplied filters as CSV or XLSX. Uses the same filters as the list endpoint but skips pagination. With `include_metrics=true` (the default), each row also includes totals over the selected date range for `agent_traffic`, `citations`, and `ai_referrals`, plus a percent-change column comparing the first and last buckets of the range — matching the totals and trend percentages shown in the sitemap UI. Limits: - Maximum 10,000 rows per export. - Maximum 366-day window for `start_date`/`end_date`. The response sets `Content-Disposition` with a `sitemap-{brand_id}-{YYYY-MM-DD}.{csv|xlsx}` filename. # Get Sitemap Page Source: https://developers.scrunch.com/api-reference/sitemap/get-sitemap-page /api-reference/openapi.json get /{brand_id}/sitemap/pages/{page_id} Get detailed information about a single page in the brand's sitemap, including title, description, depth, audit score, canonical URL, last-indexed timestamp, priority flag, and optimized-content flag. # Get Sitemap Page Metrics Source: https://developers.scrunch.com/api-reference/sitemap/get-sitemap-page-metrics /api-reference/openapi.json get /{brand_id}/sitemap/pages/{page_id}/metrics Return time-series performance metrics for a single page: citations, AI referrals, and AI agent traffic. Each metric is reported as a list of buckets keyed by date, with counts broken down by AI platform. Granularity is chosen automatically based on the requested date range — short ranges return daily buckets, longer ranges return weekly buckets. Date ranges are capped at 366 days. # List Sitemap Pages Source: https://developers.scrunch.com/api-reference/sitemap/list-sitemap-pages /api-reference/openapi.json get /{brand_id}/sitemap/pages List pages discovered in the brand's sitemap with their title, description, depth, audit score, priority flag, and optimized-content flag. Results come from the most recent completed crawl for the brand. Supports filtering by domain, URL depth, path prefix, priority flag, optimized-content flag, and a case-insensitive substring search across the page URL and title. Results are paginated and ordered by depth then URL. # Sitemap API: Pages, Audit Scores, AI Metrics Source: https://developers.scrunch.com/api-reference/sitemap/overview List, inspect, and export pages from your brand's sitemap with audit scores, citations, AI referrals, and bot traffic metrics for each URL. ## Overview The Sitemap API exposes the pages Scrunch has discovered while crawling your brand's sites, together with their AI search readiness audit score, priority and optimized-content flags, and per-page time-series metrics for citations, AI referrals, and AI agent traffic. Use it to enumerate the pages in your sitemap, drill into a single page, pull its performance trend, or dump everything to CSV or XLSX for downstream reporting. All endpoints are read-only and return data from the most recent completed (non-stale) crawl for the brand. *** ## What the Sitemap API includes * The pages from the brand's latest finished crawl, paginated and filterable * Title, meta description, depth, canonical URL, and most recent audit score * Priority flag (matches the brand's `priority_page` and `priority_path` overrides) * Optimized-content flag (page has active AXP content deployed) * Per-page time-series for citations, AI referrals, and AI agent traffic, bucketed daily or weekly * A full CSV or XLSX export that mirrors the filters, columns, and trend percentages from the sitemap view in the Scrunch dashboard *** ## When to use the Sitemap API Use the Sitemap API when you need to: * Build a content inventory for the brand from the latest crawl * Identify priority pages or pages missing optimized content * Pull per-page citations, AI referrals, or agent traffic for a custom dashboard * Export the sitemap (with totals and trends) to a spreadsheet for review For aggregated bot traffic across a whole site, use the [Agent Traffic API](/api-reference/agent-traffic/overview) instead. *** ## Endpoints | Method | Path | Purpose | | ------ | --------------------------------------------- | -------------------------------------------- | | GET | `/{brand_id}/sitemap/pages` | Paginated list of pages with filters. | | GET | `/{brand_id}/sitemap/pages/{page_id}` | Detail for a single page. | | GET | `/{brand_id}/sitemap/pages/{page_id}/metrics` | Time-series metrics for one page. | | GET | `/{brand_id}/sitemap/export` | CSV or XLSX export of the filtered page set. | All endpoints require a bearer token with `query` scope. See [Authentication](/getting-started/authentication). *** ## Filters The list and export endpoints share the same filter set: | Filter | Description | | ----------------------- | ----------------------------------------------------------------------------------------- | | `domain` | Restrict to a specific domain when the brand has multiple registered sites. | | `max_depth` | Maximum URL path depth (`0` = root only). | | `path_prefix` | Segment-aligned path prefix. `/blog` matches `/blog` and `/blog/post` but not `/blogger`. | | `is_priority` | Keep only (or exclude) pages flagged as priority for the brand. | | `has_optimized_content` | Keep only (or exclude) pages with active AXP optimized content. | | `search` | Case-insensitive substring match on the page URL or title. | The list endpoint additionally supports `limit` and `offset` for pagination. *** ## Example: list pages ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/sitemap/pages?max_depth=2&is_priority=true&limit=20" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` **Response:** ```json theme={null} { "items": [ { "id": 9087, "url": "https://example.com/products/widgets", "title": "Widgets — Example", "description": "Our flagship widget lineup.", "depth": 2, "audit_score": 84, "canonical_url": "https://example.com/products/widgets", "is_priority": true, "has_optimized_content": false } ], "total": 1, "offset": 0, "limit": 20, "domain": "example.com", "last_crawl_completed": "2025-05-08T03:14:00Z" } ``` *** ## Example: per-page metrics ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/sitemap/pages/9087/metrics?start_date=2025-04-01&end_date=2025-05-01" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" ``` The response returns three series (`citations`, `ai_referrals`, `agent_traffic`), each as a list of buckets keyed by ISO date with counts split by AI platform. Granularity (`daily` or `weekly`) is chosen automatically based on the requested range. *** ## Example: export to XLSX ```bash theme={null} curl -X GET \ "https://api.scrunchai.com/v1/1234/sitemap/export?format=xlsx&include_metrics=true&start_date=2025-04-01&end_date=2025-05-01" \ -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ -o sitemap.xlsx ``` With `include_metrics=true` (the default), each row carries totals for `agent_traffic`, `citations`, and `ai_referrals` over the supplied date range, plus a percent-change column comparing the first and last buckets — matching the trend percentages shown in the dashboard. The filename comes from the response's `Content-Disposition` header. *** ## Limits and behavior * The export endpoint caps at **10,000 rows** per call. Tighten the filters or contact support for a bulk export. * The metrics and export endpoints cap the `start_date`/`end_date` window at **366 days**. * All endpoints read from the most recent completed, non-stale crawl. If no crawl has finished, the list endpoint returns `404`. * User-controlled strings (URL, title, description, canonical URL) are sanitized in CSV and XLSX output to prevent spreadsheet formula injection. *** ## Best practices * Use `path_prefix` to scope queries to a section of the site rather than filtering client-side. * Use `search` for find-as-you-type style flows; it matches the dashboard's "Find pages…" input. * Pull metrics in **weekly** granularity (longer ranges) for trend reporting; the API chooses this automatically when the range exceeds the daily cap. * Pair `is_priority=true` with the export endpoint to produce a focused priority-page report. # Update Brand Source: https://developers.scrunch.com/api-reference/update-brand /api-reference/openapi.json patch /brands/{brand_id} Partially update a brand. Only fields included in the request body are modified. For competitors and personas, the provided list represents the full desired state: include an `id` to update an existing record, omit `id` to create a new one, and any existing records not in the list are archived. If you submit a persona without an `id` and its `name` matches a previously archived persona on the same brand, the archived persona is reactivated (its `status` returns to `active` and its `description` is updated) instead of creating a duplicate. This avoids unique-name conflicts when reusing a name that was previously archived. # Update Competitor Source: https://developers.scrunch.com/api-reference/update-competitor /api-reference/openapi.json put /brands/{brand_id}/competitors/{competitor_id} Update a competitor # Update Persona Source: https://developers.scrunch.com/api-reference/update-persona /api-reference/openapi.json put /brands/{brand_id}/personas/{persona_id} Update a persona # Webhooks: Pipeline Stage Completion Callbacks Source: https://developers.scrunch.com/api-reference/webhooks/overview Subscribe to real-time webhook callbacks for Optimize and Deploy pipeline events including audit, optimization, and AXP deployment completion. Webhook documentation is coming soon. Contact your Customer Success representative for early access setup instructions. Webhooks let you receive HTTP callbacks at each stage of the Optimize and Deploy pipeline — eliminating the need to poll for status. ## Events | Event | Fired when | | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | | `audit.completed` | A page audit finishes | | `optimization.completed` | Content optimization finishes. Payload includes `status: "staged"` when optimized content was staged to AXP via `stage_axp: true`. | | `deployment.completed` | An AXP deployment finishes | | `pipeline.completed` | All URLs in a batch have finished | ## Coming soon Full documentation including payload schemas, signature verification, and retry behavior will be published here when webhooks reach general availability. # Provision an API key Source: https://developers.scrunch.com/getting-started/authentication Create, scope, and rotate Scrunch API keys at the organization level to authenticate Query, Responses, Configuration, and Agent Traffic requests. Scrunch API keys authenticate your requests and define which brands and operations your integration can access. Only organization admins can create or manage API keys. API keys are shown **once** at creation time. Be sure to copy and store them securely. ## Plan Requirements API key creation is available on the **Agency** and **Enterprise** plans. If your organization is on a different plan, the **New API Key** button is disabled and you'll see an upgrade prompt when attempting to create one. If you need API access on another plan, contact [support@scrunchai.com](mailto:support@scrunchai.com) to discuss an override for your organization. Attempts to call `POST /organizations/{organization_id}/api-keys` without the required plan capability return HTTP `402 Payment Required`. ## Where API Keys Live API keys are managed at the organization level. You can find them by clicking your **organization name** in the top-left corner of the Scrunch dashboard, then selecting **API Keys**. This area is available only to organization admins and is also where you manage brands and archival operations. ## Create an API Key Complete these steps in your Scrunch UI to provision an API Key (`$SCRUNCH_API_TOKEN`). Click your **organization name** in the top-left corner of the Scrunch dashboard. Organization selector showing API access Select **API Keys** from the organization menu. Screenshot 2026 03 05 At 2 07 51 PM Click **+ New API Key**. Scrunch supports several operational scopes: * Query (retrieve analytics and metrics) * Configure (update brand configuration, prompts, etc.) * Create Brand (programmatically create brands) Choose the minimal scope required for your integration. Screenshot 2026 03 05 At 2 08 43 PM You may scope the key to: * **Specific brand(s)** (recommended for client-facing reporting) * **All brands** (recommended for internal tooling or ETL pipelines) Scrunch displays the key **once**. Copy it immediately and store it securely. ## Use Your API Key Include your key as a Bearer token in the `Authorization` header. ```bash theme={null} export SCRUNCH_API_TOKEN="your-key" curl -H "Authorization: Bearer $SCRUNCH_API_TOKEN" \ https://api.scrunchai.com/v1/brands ``` ## Best Practices Limit access when integrating with client-facing dashboards or BI tools. Use for internal workflows only (e.g., multi-brand ETL, automation). Especially important for deployments or CI environments. Keeps your organization clean and prevents accidental access. ## Troubleshooting If you don't see the **API Keys** tab, you are likely not an organization admin. Contact your Scrunch admin or [support@scrunchai.com](mailto:support@scrunchai.com). If a key cannot access a brand: * Verify the key's scope includes that brand * Check that the brand has not been archived # Optimize and Deploy Quickstart Source: https://developers.scrunch.com/getting-started/quickstart-orchestration Step-by-step guide to submitting pages for AI search audit, content optimization, and AXP deployment using a single Scrunch pipeline API call. The Optimize and Deploy API is currently in **early access**. Contact your Customer Success representative to get access enabled for your organization. ### Prerequisites * A Scrunch workspace with **Optimize and Deploy** access enabled * An API key with **Configure** access * A **brand ID** for the brand you want to optimize * (Optional) A **site ID** if you want to deploy to AXP *** ### Run your first pipeline ```bash theme={null} export SCRUNCH_API_KEY="your-api-key-here" export SCRUNCH_BRAND_ID="your-brand-id" ``` This example submits two URLs for audit and content optimization: ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/$SCRUNCH_BRAND_ID" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "urls": [ "https://example.com/page-a", "https://example.com/page-b" ], "optimize": true }' ``` **Example response:** ```json theme={null} { "pipeline_id": null, "tokens": [ { "token": "01JABC00000000000000001", "url": "https://example.com/page-a", "status": "pending", "orchestration_status": "audit" }, { "token": "01JABC00000000000000002", "url": "https://example.com/page-b", "status": "pending", "orchestration_status": "audit" } ], "status": "pending" } ``` Use a token from the response to check progress: ```bash theme={null} curl "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/$SCRUNCH_BRAND_ID/01JABC00000000000000001" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` **Example response (completed):** ```json theme={null} { "token": "01JABC00000000000000001", "url": "https://example.com/page-a", "status": "completed", "orchestration_status": "completed", "optimization_run_id": "01JOPTRUN0000000000000", "axp_version_id": null, "result": { "checks": [], "access_controls_score": 100, "content_delivery_score": 90, "content_quality_score": 85 }, "created_at": "2025-02-06T10:00:00Z", "updated_at": "2025-02-06T10:02:30Z" } ``` ```bash theme={null} pip install requests ``` ```python theme={null} import requests import time API_KEY = "your-api-key" BRAND_ID = "your-brand-id" BASE = f"https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/{BRAND_ID}" HEADERS = {"Authorization": f"Bearer {API_KEY}"} # Submit URLs resp = requests.post(BASE, headers=HEADERS, json={ "urls": [ "https://example.com/page-a", "https://example.com/page-b", ], "optimize": True, }, timeout=30) resp.raise_for_status() pipeline = resp.json() # Poll each token until done for record in pipeline["tokens"]: token = record["token"] while True: status = requests.get( f"{BASE}/{token}", headers=HEADERS, timeout=30 ).json() stage = status["orchestration_status"] print(f"{token}: {stage}") if stage in ("completed", "failed"): break time.sleep(5) ``` ```bash theme={null} python orchestration.py ``` ```bash theme={null} npm install axios ``` ```javascript theme={null} import axios from "axios"; const API_KEY = "your-api-key"; const BRAND_ID = "your-brand-id"; const BASE = `https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/${BRAND_ID}`; const headers = { Authorization: `Bearer ${API_KEY}` }; async function main() { // Submit URLs const { data: pipeline } = await axios.post(BASE, { urls: [ "https://example.com/page-a", "https://example.com/page-b", ], optimize: true, }, { headers }); // Poll each token for (const record of pipeline.tokens) { let stage = record.orchestration_status; while (stage !== "completed" && stage !== "failed") { await new Promise((r) => setTimeout(r, 5000)); const { data: status } = await axios.get( `${BASE}/${record.token}`, { headers } ); stage = status.orchestration_status; console.log(`${record.token}: ${stage}`); } } } main().catch(console.error); ``` ```bash theme={null} node orchestration.js ``` *** ## Next steps Learn about pipeline stages, error codes, and request patterns. Walk through the full lifecycle from submission to completion. Get notified in real time instead of polling. # Query API Quickstart Source: https://developers.scrunch.com/getting-started/quickstart-query Step-by-step walkthrough for your first Scrunch Query API call to fetch weekly brand presence, sentiment, and AI visibility metrics by platform. ### Prerequisites * A Scrunch workspace * An API key with **Query** access * A **brand ID** for the brand you want to query *** ### Call the API Get your API key from **Organization Settings → API Keys** and set it as environment variables: ```bash theme={null} export SCRUNCH_API_KEY="your-api-key-here" export SCRUNCH_BRAND_ID="your-brand-id" ``` This example retrieves **weekly brand presence** for the last 30 days. ```bash theme={null} curl "https://api.scrunchai.com/v1/$SCRUNCH_BRAND_ID/query?fields=date_week,brand_presence_percentage&start_date=2025-01-01&end_date=2025-01-31" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" \ -H "Accept: application/json" ``` **Example output:** ```json theme={null} { "total": 4, "limit": 1000, "offset": 0, "rows": [ { "date_week": "2025-01-06", "brand_presence_percentage": 42.1 }, { "date_week": "2025-01-13", "brand_presence_percentage": 47.8 } ] } ``` ```bash theme={null} pip install requests pandas ``` ```python theme={null} import requests import pandas as pd API_KEY = "your-api-key" BRAND_ID = "your-brand-id" BASE_URL = f"https://api.scrunchai.com/v1/{BRAND_ID}/query" params = { "fields": "date_week,brand_presence_percentage", "start_date": "2025-01-01", "end_date": "2025-01-31", } response = requests.get( BASE_URL, headers={"Authorization": f"Bearer {API_KEY}"}, params=params, timeout=30, ) response.raise_for_status() data = response.json() df = pd.DataFrame(data) print(df) ``` ```bash theme={null} python quickstart.py ``` ```bash theme={null} npm install axios ``` ```javascript theme={null} import axios from "axios"; const API_KEY = "your-api-key"; const BRAND_ID = "your-brand-id"; async function main() { const url = `https://api.scrunchai.com/v1/${BRAND_ID}/query`; const response = await axios.get(url, { headers: { Authorization: `Bearer ${API_KEY}` }, params: { fields: "date_week,brand_presence_percentage", start_date: "2025-01-01", end_date: "2025-01-31", }, }); console.log(response.data.rows); } main().catch(console.error); ``` ```bash theme={null} node quickstart.js ``` *** ## Next steps Learn how fields, dimensions, and metrics work together. Send Query data into Looker Studio or your BI tool. Get full answers, citations, and sentiment when you need row-level detail. # Responses API Quickstart Source: https://developers.scrunch.com/getting-started/quickstart-responses Use the Responses API to retrieve full AI answers, citations, sentiment, competitors, and metadata for every Scrunch prompt execution. ### Prerequisites * A Scrunch workspace * An API key with **Responses** access * A **brand ID** for the brand you want to fetch responses for > The Responses API returns **row-level data**. It is ideal for warehouses, BI tools, audits, DE workflows, and custom analysis. You may need to reach out to your Scrunch rep for Responses API access *** ### Call the API ```bash theme={null} export SCRUNCH_API_KEY="your-api-key-here" export SCRUNCH_BRAND_ID="your-brand-id" ``` This example retrieves responses for a single day (Scrunch recommends syncing by date windows). ```bash theme={null} curl "https://api.scrunchai.com/v1/$SCRUNCH_BRAND_ID/responses?start_date=2025-01-01&end_date=2025-01-02&limit=100" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" \ -H "Accept: application/json" ``` **Example output:** ```json theme={null} { "total": 128, "limit": 100, "offset": 0, "items": [ { "id": "resp_01jk93mc9p", "created_at": "2025-01-01T05:12:41.000Z", "prompt_id": "pr_01hd8j39s", "prompt": "Which mattress brands are recommended for side sleepers?", "platform": "chatgpt", "brand_present": true, "brand_sentiment": "positive", "brand_position": 1, "response_text": "For side sleepers, the best mattresses tend to...", "citations": [ { "url": "https://www.example.com/review", "title": "2024 mattress comparison", "source_type": "other" } ], "competitors": [ { "name": "Casper", "present": true, "sentiment": "neutral" }, { "name": "Purple", "present": true, "sentiment": "positive" } ], "tags": ["mattress", "comparison"], "stage": "evaluation" } ] } ``` Use the `offset` parameter to retrieve subsequent batches: ```bash theme={null} curl "https://api.scrunchai.com/v1/$SCRUNCH_BRAND_ID/responses?start_date=2025-01-01&end_date=2025-01-02&limit=100&offset=100" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` ```bash theme={null} pip install requests pandas ``` ```python theme={null} import requests import pandas as pd API_KEY = "your-api-key" BRAND_ID = "your-brand-id" BASE_URL = f"https://api.scrunchai.com/v1/{BRAND_ID}/responses" params = { "start_date": "2025-01-01", "end_date": "2025-01-02", "limit": 100, "offset": 0 } all_rows = [] while True: response = requests.get( BASE_URL, headers={"Authorization": f"Bearer {API_KEY}"}, params=params, timeout=60 ) response.raise_for_status() data = response.json() items = data["items"] all_rows.extend(items) if params["offset"] + params["limit"] >= data["total"]: break params["offset"] += params["limit"] df = pd.DataFrame(all_rows) print(df.head()) ``` ```bash theme={null} python responses_quickstart.py ``` ```bash theme={null} npm install axios ``` ```javascript theme={null} import axios from "axios"; const API_KEY = "your-api-key"; const BRAND_ID = "your-brand-id"; async function fetchResponses() { let offset = 0; const limit = 100; const all = []; while (true) { const res = await axios.get( `https://api.scrunchai.com/v1/${BRAND_ID}/responses`, { headers: { Authorization: `Bearer ${API_KEY}` }, params: { start_date: "2025-01-01", end_date: "2025-01-02", limit, offset, }, } ); all.push(...res.data.items); if (offset + limit >= res.data.total) break; offset += limit; } console.log(all.slice(0, 3)); } fetchResponses().catch(console.error); ``` ```bash theme={null} node responses.js ``` *** ## When to use the Responses API Use the Responses API when you need: * Full AI-generated answers * Citations and source URLs used in responses * Per-response presence, position, sentiment * Competitor mentions * Metadata (stage, tags, topics, platform, persona) * Warehouse or BI-level granularity *** ## Next steps Explore the response schema and filtering options. Learn how to sync Responses into BigQuery, Snowflake, or Redshift. Use Query for trends, aggregates, comparisons, and dashboards. # Send Agent Traffic via API Source: https://developers.scrunch.com/guides/agent-traffic-api-integration Forward AI bot traffic logs to Scrunch from any CDN, edge worker, or hosting environment using the custom Agent Traffic ingestion endpoint and JSON or NDJSON. ## Overview The Agent Traffic API lets you send web traffic logs to Scrunch from any platform or hosting environment — including CDNs and setups that don't have a native Scrunch integration. Once data is flowing, Scrunch automatically classifies each request by bot type (retrieval, training, indexer) and agent source (GPTBot, ClaudeBot, and others). Once connected, the Agent Traffic dashboard will show: * Total bot traffic for the selected period and a comparison to the prior period * Bot traffic over time and distribution across Retrieval, Indexer, and Training types * Top bot agents and when they were last seen * Top content pages accessed by LLM bots * Recent bot requests * A date filter for the last 24 hours, 7 days, or 30 days This guide covers: * Setting up a site with the API platform in the dashboard * Sending single events and batches * Backfilling historical log data * Managing multiple sites (for agencies and multi-brand setups) * Retry logic and error handling *** ## Prerequisites * A Scrunch account with Agent Traffic access * Access to your web server or CDN access logs * Your site's domain (e.g., `example.com`) *** ## Step 1: Create a site with the API platform 1. In the Scrunch dashboard, open the **Agent Traffic** page. 2. Click **+ Connect Site**. 3. Enter your domain and select **API** as the platform. 4. A dedicated instructions page will appear showing your **Site ID**, **Webhook URL**, and **API Key**. Copy all three — you will need them for every request. Each site has its own endpoint and key. Don't reuse them across different sites or integrations. Your site will show a **pending** status until the first valid request is received. It transitions to **active** automatically within 5–10 minutes. Screenshot 2026 04 27 At 1 25 17 PM *** ## Step 2: Send your first event ### Endpoint ```text theme={null} POST https://webhooks.scrunchai.com/v1/sites/{site_id}/platforms/custom/web-traffic ``` ### Authentication Include the API key in the `X-Api-Key` header: ```text theme={null} X-Api-Key: ``` Screenshot 2026 04 27 At 1 26 12 PM ### Required fields | Field | Type | Description | | ------------- | ---------------- | ----------------------------------------------------- | | `domain` | string | The domain of the site (e.g. `example.com`) | | `user_agent` | string | The full, original User-Agent string from the request | | `url` | string | Full URL (e.g. `https://example.com/blog/post`) | | `path` | string | URL path only (e.g. `/blog/post`) | | `method` | string | HTTP method (e.g. `GET`) | | `status_code` | integer | HTTP response status code (e.g. `200`) | | `timestamp` | integer \| float | Unix epoch in seconds (e.g. `1700000000`) | ### Optional fields | Field | Type | Description | | --------------- | ------- | ----------------------------------- | | `response_time` | integer | Response time in milliseconds | | `ip` | string | IP address of the requesting client | Always pass the **original, unmodified** `user_agent` string from the incoming request. Scrunch's bot classification runs entirely off this field. Truncating or transforming it will result in incorrect or missing bot detection. ### Single event (cURL) Use `Content-Type: application/json` and send one JSON object per request: ```bash theme={null} curl -X POST "https://webhooks.scrunchai.com/v1/sites/{site_id}/platforms/custom/web-traffic" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY" \ -d '{ "domain": "example.com", "user_agent": "Mozilla/5.0 (compatible; GPTBot/1.0; +https://openai.com/gptbot)", "url": "https://example.com/blog/post", "path": "/blog/post", "method": "GET", "status_code": 200, "timestamp": 1700000000, "response_time": 120, "ip": "203.0.113.1" }' ``` A successful response returns: ```json theme={null} { "status": "ok" } ``` *** ## Step 3: Send batches with NDJSON For production use, send multiple events per request using newline-delimited JSON (NDJSON). Each line is a complete JSON object. This reduces request overhead and is the recommended approach for any significant traffic volume. Use `Content-Type: application/x-ndjson`: ```bash theme={null} curl -X POST "https://webhooks.scrunchai.com/v1/sites/{site_id}/platforms/custom/web-traffic" \ -H "Content-Type: application/x-ndjson" \ -H "X-Api-Key: YOUR_API_KEY" \ -d '{"domain":"example.com","user_agent":"Mozilla/5.0 (compatible; GPTBot/1.0)","url":"https://example.com/page-1","path":"/page-1","method":"GET","status_code":200,"timestamp":1700000000} {"domain":"example.com","user_agent":"Mozilla/5.0 (compatible; ClaudeBot/1.0)","url":"https://example.com/page-2","path":"/page-2","method":"GET","status_code":200,"timestamp":1700000060,"response_time":95}' ``` Keep each batch **under 1 MB uncompressed**. Split larger payloads into multiple requests. *** ## Step 4: Verify your integration After sending your first request, wait up to 5–10 minutes for your site to show as **Active** in Scrunch. If you don't see traffic appearing, send a test event using a known bot User-Agent to confirm your credentials and pipeline are working: ```bash theme={null} curl -X POST "https://webhooks.scrunchai.com/v1/sites/{site_id}/platforms/custom/web-traffic" \ -H "Content-Type: application/json" \ -H "X-Api-Key: YOUR_API_KEY" \ -d '{ "domain": "yourdomain.com", "user_agent": "Mozilla/5.0 (compatible; GPTBot/1.0; +https://openai.com/gptbot)", "url": "https://yourdomain.com/test-page", "path": "/test-page", "method": "GET", "status_code": 200, "timestamp": 1700000000 }' ``` If this returns `{ "status": "ok" }` but traffic still doesn't appear after 10 minutes, check the troubleshooting section below. *** ## Step 5: Backfill historical data with Python If you have existing access logs, use this script to send them in batches. It reads a CSV of log entries, maps fields to the API schema, and sends NDJSON batches with retry handling for rate limits. ### Expected CSV format Your CSV should have columns matching the required and optional fields. At minimum: ```text theme={null} timestamp,domain,user_agent,url,path,method,status_code,response_time_ms,ip_address 1700000000,example.com,"Mozilla/5.0 (compatible; GPTBot/1.0)",https://example.com/page,/page,GET,200,120,203.0.113.1 ``` ### Backfill script ```python theme={null} import csv import json import time import requests API_KEY = "your-jwt-token" SITE_ID = "your-site-id" ENDPOINT = f"https://webhooks.scrunchai.com/v1/sites/{SITE_ID}/platforms/custom/web-traffic" BATCH_SIZE_BYTES = 1_000_000 # 1 MB per batch def load_payloads(csv_path: str) -> list[dict]: """Read a CSV of access log rows and map to API payload format.""" payloads = [] with open(csv_path, encoding="utf-8") as f: reader = csv.DictReader(f) for row in reader: domain = row.get("domain", "") path = row.get("path", "/") or "/" payload = { "domain": domain, "user_agent": row.get("user_agent", ""), "url": row.get("url", "") or f"https://{domain}{path}", "path": path, "method": row.get("method", "GET") or "GET", "status_code": int(row.get("status_code", "200") or "200"), "timestamp": int(row.get("timestamp", "0") or "0"), "response_time": int(row.get("response_time_ms", "0") or "0"), "ip": row.get("ip_address") or None, } payloads.append(payload) return payloads def build_batches(payloads: list[dict], max_bytes: int = BATCH_SIZE_BYTES) -> list[list[dict]]: """Split payloads into batches that fit within max_bytes uncompressed.""" batches, current, current_size = [], [], 0 for p in payloads: size = len(json.dumps(p).encode()) + 1 # +1 for newline if current and current_size + size > max_bytes: batches.append(current) current, current_size = [], 0 current.append(p) current_size += size if current: batches.append(current) return batches def send_batch(batch: list[dict], retries: int = 3) -> None: """Send a single NDJSON batch with retry logic for rate limits.""" ndjson = "\n".join(json.dumps(p) for p in batch) + "\n" for attempt in range(retries): response = requests.post( ENDPOINT, content=ndjson.encode("utf-8"), headers={ "Content-Type": "application/x-ndjson", "X-Api-Key": API_KEY, }, timeout=60, ) if response.status_code == 200: return if response.status_code == 429: wait = int(response.headers.get("Retry-After", 5)) print(f"Rate limited. Retrying in {wait}s...") time.sleep(wait) else: response.raise_for_status() raise RuntimeError(f"Failed to send batch after {retries} attempts") def main(csv_path: str) -> None: payloads = load_payloads(csv_path) batches = build_batches(payloads) print(f"Loaded {len(payloads)} events across {len(batches)} batch(es)") for i, batch in enumerate(batches, 1): print(f"Sending batch {i}/{len(batches)} ({len(batch)} events)...") send_batch(batch) print(f" Batch {i} sent successfully") print("Done.") if __name__ == "__main__": import sys main(sys.argv[1]) ``` Run it: ```bash theme={null} python backfill.py your_logs.csv ``` *** ## Managing multiple sites If you are an agency or managing multiple brands, each domain requires its own site entry in the dashboard with its own Site ID and API key. Never reuse credentials across sites — each site's key is scoped to that domain only. The sending logic is identical across all sites — only the `site_id` in the URL and the `X-Api-Key` header change per site. A common pattern for multi-site setups: ```python theme={null} SITES = [ {"site_id": "01ABC...", "api_key": "token-for-site-a", "domain": "brand-a.com"}, {"site_id": "01DEF...", "api_key": "token-for-site-b", "domain": "brand-b.com"}, ] for site in SITES: # filter payloads for this domain, then send site_payloads = [p for p in all_payloads if p["domain"] == site["domain"]] # ... send using site["site_id"] and site["api_key"] ``` This approach scales well when onboarding many brands: provision each site in the dashboard, collect credentials, and run the same pipeline with different configuration per site. *** ## Tips for better results * **Use NDJSON batching** to reduce request overhead for high-traffic sites. * **Keep batch sizes under 1 MB** uncompressed for optimal performance. * **Always pass the original, unmodified User-Agent string** — Scrunch uses it to classify the bot. Never transform or truncate it. * **Exclude static asset paths** (CSS, JS, images) if you want cleaner data focused on content pages. * **Include paths that serve PDFs** — AI bots frequently request them. * **Never reuse credentials across sites** — provision a separate Site ID and API key for each domain. *** ## Error handling | Status | Meaning | Action | | ------ | -------------------------- | ------------------------------------------------------------- | | `200` | Accepted and queued | No action needed | | `401` | Invalid or missing API key | Verify the `X-Api-Key` value and header name | | `422` | Validation error | Check all required fields are present and correctly typed | | `429` | Rate limited | Wait and retry; respect the `Retry-After` response header | | `500` | Server error | Retry with exponential backoff; contact support if persistent | *** ## Troubleshooting **Site is stuck in pending status** The site activates within 5–10 minutes of the first valid request. If it remains pending, confirm a request was actually sent (not a dry run), check that the Site ID in the URL matches the one in the dashboard, and verify the API key is correct. Use the verification cURL in Step 4 to test with a known bot user-agent. **Bot traffic is not being classified** Bot classification is derived entirely from the `user_agent` field. Confirm you are passing the raw, original user-agent string from the incoming request without modification. Check your log format — some CDNs normalize or truncate user-agent strings before writing them to logs. If so, use a logging integration that captures the original header. **Getting 422 errors** The most common cause is a missing required field or an incorrect type. Check that `timestamp` is a Unix epoch number (not ISO 8601), `status_code` is an integer (not a string), and `path` starts with a `/`. **NDJSON batches are being rejected** Each line must be a complete, valid JSON object with no embedded newlines. The `Content-Type` header must be exactly `application/x-ndjson`. Keep batch size under 1 MB uncompressed. **Don't see traffic after 10 minutes** Confirm your Webhook URL and API Key match exactly what's shown in your Scrunch app. Check that your `Content-Type` header matches the body format (`application/json` for single events, `application/x-ndjson` for batches). Confirm your `timestamp` is a Unix epoch in seconds, not milliseconds. *** ## Related * [Agent Traffic API Overview](/api-reference/agent-traffic/overview) — Full schema and response format for querying traffic data * [Get Agent Traffic](/api-reference/agent-traffic/get-agent-traffic) — Query aggregated bot traffic by date, path, and agent type * [CDN Integration Guides](/integrations/agent-traffic) — Native integrations for Cloudflare, Fastly, and other CDN platforms # Load a Data Mart from the Responses API Source: https://developers.scrunch.com/guides/data-mart-loading Incrementally load response-level data from the Scrunch Responses API, normalize it into fact and dimension tables, and compute metrics in your warehouse. Build a data mart from the Scrunch Responses API by incrementally loading response-level data, normalizing it into fact and dimension tables, and computing metrics in your warehouse. *** ## Prerequisites * A Scrunch API key with **Responses** access ([provision one here](/getting-started/authentication)) * A **brand ID** for the brand you want to load * A cloud data warehouse (BigQuery, Snowflake, Redshift, Databricks, etc.) *** ## How the Responses API works The Responses API returns one record per AI response. Each record includes the full response text, citations, brand and competitor evaluations, and prompt metadata. Key characteristics: * **1:1 response model** — each item represents a single, distinct AI response * **Denormalized** — arrays like `tags`, `competitors`, and `citations` are embedded in each record * **Reverse chronological** — newest responses are returned first * **Supports date filtering and pagination** — ideal for incremental ETL For the full response schema, see the [Responses API overview](/api-reference/responses/overview). *** ## Incremental loading strategy Use date windows and pagination to pull new responses on a recurring schedule. Use `start_date` and `end_date` (both `YYYY-MM-DD`, UTC) to define a date range. For daily loads, pull the previous UTC day after midnight to ensure completeness. The API returns paginated results. Increment `offset` by `limit` until you have all records for the window. ```bash theme={null} curl "https://api.scrunchai.com/v1/$BRAND_ID/responses?start_date=2025-06-01&end_date=2025-06-02&limit=1000&offset=0" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` The response includes a `total` count so you know when you're done: ```json theme={null} { "total": 2430, "offset": 0, "limit": 1000, "items": [ ... ] } ``` Each response has a globally unique `id`. Use it as a natural key and upsert into your warehouse to handle re-runs or overlapping date windows. Some fields like `brand_present`, `brand_sentiment`, `tags`, and `stage` may be re-evaluated if prompt metadata or brand configuration changes in Scrunch. Always upsert rather than append-only. *** ## Schema design Each API record includes arrays (`tags`, `competitors`, `citations`) that should be normalized into separate tables to avoid row explosion. ``` responses (1 row per response) | |—— response_tags (1 row per response x tag) | |—— response_competitors (1 row per response x competitor) | |—— response_citations (1 row per response x citation) ``` If your warehouse has strong support for JSON or `ARRAY` columns (e.g., BigQuery, Snowflake, Databricks), you can skip the bridge tables and store `tags`, `competitors`, and `citations` as native array or JSON fields directly on the responses table. Use `UNNEST` or `LATERAL FLATTEN` at query time instead of pre-normalizing. This simplifies your ETL at the cost of slightly more complex analytics queries. ### Responses fact table Store one row per response with scalar fields: | Column | Type | Notes | | ----------------- | ----------- | ------------------------------------------ | | `id` | `STRING` | Primary key (globally unique) | | `created_at` | `TIMESTAMP` | When the response was captured | | `prompt_id` | `STRING` | Foreign key to the prompt | | `prompt` | `STRING` | Text of the prompt | | `platform` | `STRING` | ChatGPT, Perplexity, Claude, etc. | | `persona_id` | `STRING` | | | `persona_name` | `STRING` | | | `stage` | `STRING` | Funnel stage enum | | `branded` | `BOOLEAN` | Whether the prompt includes brand names | | `brand_present` | `BOOLEAN` | | | `brand_sentiment` | `STRING` | `positive`, `mixed`, `negative`, or `null` | | `brand_position` | `STRING` | `top`, `middle`, `bottom`, or `null` | | `country` | `STRING` | | | `response_text` | `STRING` | Full AI-generated answer (markdown) | ### Bridge tables Unnest each array into its own table, keyed by `response_id`. **response\_tags** | Column | Type | | ------------- | -------- | | `response_id` | `STRING` | | `tag` | `STRING` | **response\_competitors** | Column | Type | | ----------------- | --------- | | `response_id` | `STRING` | | `competitor_name` | `STRING` | | `present` | `BOOLEAN` | | `sentiment` | `STRING` | | `position` | `STRING` | **response\_citations** | Column | Type | | ------------- | -------- | | `response_id` | `STRING` | | `url` | `STRING` | | `title` | `STRING` | | `snippet` | `STRING` | | `source_type` | `STRING` | Never unnest multiple arrays in the same query. Crossing two arrays (e.g., tags x competitors) causes row explosion and inflates every metric. *** ## Computing metrics Once your data mart is loaded, you can aggregate responses into daily performance summaries. Group on `DATE(created_at), prompt_id, prompt, platform` to match the way Scrunch reports prompt-level performance by default. The following examples use PostgreSQL syntax. Translate as needed for your warehouse. ### Response count ```sql theme={null} COUNT(*) AS responses ``` ### Brand presence percentage ```sql theme={null} COUNT(*) FILTER (WHERE brand_present = true)::float / NULLIF(COUNT(*)::float, 0.0) AS brand_presence_pct ``` ### Brand sentiment score ```sql theme={null} AVG( CASE WHEN brand_sentiment = 'positive' THEN 100 WHEN brand_sentiment = 'mixed' THEN 50 WHEN brand_sentiment = 'negative' THEN 0 ELSE NULL END ) AS brand_sentiment_score ``` ### Brand position score ```sql theme={null} AVG( CASE WHEN brand_position = 'top' THEN 100 WHEN brand_position = 'middle' THEN 50 WHEN brand_position = 'bottom' THEN 0 ELSE NULL END ) AS brand_position_score ``` ### Putting it together ```sql theme={null} SELECT DATE(created_at) AS response_date, prompt_id, prompt, platform, COUNT(*) AS responses, COUNT(*) FILTER (WHERE brand_present)::float / NULLIF(COUNT(*)::float, 0.0) AS brand_presence_pct, AVG(CASE WHEN brand_sentiment = 'positive' THEN 100 WHEN brand_sentiment = 'mixed' THEN 50 WHEN brand_sentiment = 'negative' THEN 0 END) AS brand_sentiment_score, AVG(CASE WHEN brand_position = 'top' THEN 100 WHEN brand_position = 'middle' THEN 50 WHEN brand_position = 'bottom' THEN 0 END) AS brand_position_score FROM responses GROUP BY 1, 2, 3, 4; ``` These metric definitions match the ones used in the Scrunch dashboard and Query API. You can also define your own calculations if your use case requires it. *** ## Related Full schema, filtering, and pagination details. Make your first API call in cURL, Python, or JavaScript. # Optimize and Deploy Pipeline Lifecycle Guide Source: https://developers.scrunch.com/guides/orchestration-lifecycle Walk through every stage of the Optimize and Deploy pipeline — submitting URLs, tracking progress, polling status, handling errors, and processing results. The Optimize and Deploy API is currently in **early access**. Contact your Customer Success representative to get access enabled for your organization. ## Overview This guide walks through the complete lifecycle of an Optimize and Deploy pipeline — from submitting URLs to handling results. By the end, you'll understand how to track progress, handle errors, and integrate the pipeline into your workflow. ### Pipeline flow Each URL cascades through up to three stages. At every stage transition, a webhook fires so you can react in real time. Stages are optional — the pipeline exits early when the last enabled stage completes. Regardless of which stage is the final one, you always receive: 1. The **stage-specific webhook** for the last stage that ran (e.g., `audit.completed` if audit-only) 2. The **`pipeline.completed`** webhook once all URLs in the batch have finished ```mermaid theme={null} sequenceDiagram participant You participant API as Optimize & Deploy API participant Audit as 🔍 Site Audit participant Opt as ✨ Content Optimizer participant AXP as 🚀 AXP Deploy participant Hook as 🔔 Your Webhook You->>API: POST /orchestration/optimize-and-deploy/{brand_id} API-->>You: tokens[] + pipeline_id rect rgb(240, 248, 255) Note over Audit: Stage 1 — Always runs API->>Audit: Run audit for each URL Audit-->>API: Audit scores + checks API->>Hook: audit.completed (score, issues) Note over Hook: If optimize=false → pipeline ends here end alt optimize = true rect rgb(240, 255, 240) Note over Opt: Stage 2 — Only if optimize=true API->>Opt: Optimize content with prompts & personas Opt-->>API: Optimized title, description, content opt stage_axp = true API->>AXP: Stage optimized content (no live deploy) end API->>Hook: optimization.completed (optimization_run_id) Note over Hook: If neither deploy_axp nor stage_axp → pipeline ends here
If stage_axp=true → status="staged", pipeline ends here end end alt deploy_axp = true rect rgb(255, 248, 240) Note over AXP: Stage 3 — Only if deploy_axp=true API->>AXP: Deploy optimized content AXP-->>API: AXP version ID API->>Hook: deployment.completed (axp_version_id) end end rect rgb(245, 245, 245) Note over Hook: Always fires when all URLs finish API->>Hook: pipeline.completed (summary counts) end Note over You,API: Poll anytime with GET .../token You->>API: GET .../token API-->>You: Current status + results ``` ### Webhook events per configuration | Configuration | Webhooks fired (per URL) | Final webhook (per batch) | | ---------------------------------------------- | --------------------------------------------------------------------- | ------------------------- | | Audit only (default) | `audit.completed` | — | | Audit + optimize | `audit.completed` → `optimization.completed` | — | | Audit + optimize + stage (`stage_axp: true`) | `audit.completed` → `optimization.completed` (`status: "staged"`) | — | | Audit + optimize + deploy (`deploy_axp: true`) | `audit.completed` → `optimization.completed` → `deployment.completed` | `pipeline.completed` | `pipeline.completed` fires only for `deploy_axp: true` batches — other configurations end with the last per-URL webhook. ### What gets configured at each stage | Stage | Triggered by | Webhook event | Key data returned | | --------------------- | ------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------ | | **Site Audit** | Always runs | `audit.completed` | `score`, `issues`, `recommendations` | | **Content Optimizer** | `optimize: true` | `optimization.completed` | `optimization_run_id`, `title`, `description` | | **AXP Stage** | `stage_axp: true` + `site_id` | `optimization.completed` with `status: "staged"` | `optimization_run_id`, `title`, `description` | | **AXP Deploy** | `deploy_axp: true` + `site_id` | `deployment.completed` | `axp_version_id`, `site_id` | | **Pipeline done** | All URLs finish (`deploy_axp: true` batches only) | `pipeline.completed` | `completed_count`, `failed_count`, `total_count` | *** ## 1. Submit a pipeline ### Simple mode: shared configuration ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/1234" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "urls": ["https://example.com/page-a", "https://example.com/page-b"], "optimize": true, "target_prompts": ["best budget airlines", "cheap flights comparison"], "target_personas": [{"name": "Budget Traveler", "description": "Price-sensitive consumer"}] }' ``` ### Stage-only mode: review before going live Set `stage_axp: true` to run the full audit and optimize pipeline and push the optimized content to AXP as a staged change — without deploying a live version. Reviewers can then approve and publish from the Scrunch dashboard. ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/1234" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "urls": ["https://example.com/page-a"], "optimize": true, "stage_axp": true, "site_id": "01JEXAMPLE00000000000000" }' ``` The pipeline finishes at `orchestration_status: completed` after staging, and the final per-URL webhook is `optimization.completed` with `status: "staged"`. `stage_axp` and `deploy_axp` are mutually exclusive. ### Detailed mode: per-URL overrides ```bash theme={null} curl -X POST "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/1234" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "requests": [ { "url": "https://example.com/budget-page", "target_prompts": ["best budget airlines"], "target_personas": [{"name": "Budget Traveler"}] }, { "url": "https://example.com/luxury-page", "target_prompts": ["luxury travel options"], "override_suggestions": true } ], "optimize": true, "deploy_axp": true, "site_id": "01JEXAMPLE00000000000000" }' ``` ### What gets returned ```json theme={null} { "pipeline_id": "01JPIPELINE000000000000", "tokens": [ {"token": "01JABC001", "url": "https://example.com/budget-page", "status": "pending", "orchestration_status": "audit"}, {"token": "01JABC002", "url": "https://example.com/luxury-page", "status": "pending", "orchestration_status": "audit"} ], "status": "pending" } ``` `pipeline_id` is only set when `deploy_axp` is true — it groups all URLs into a single AXP deployment batch. *** ## 2. Track progress ### Option A: Polling ```bash theme={null} curl "https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/1234/01JABC001" \ -H "Authorization: Bearer $SCRUNCH_API_KEY" ``` | `orchestration_status` | Meaning | | ---------------------- | ------------------------------------- | | `audit` | Page audit running | | `optimizing` | Content optimization running | | `deploying` | AXP deployment running | | `completed` | All stages finished successfully | | `failed` | Pipeline stopped at the failing stage | Poll every 5–10 seconds. Audits typically complete in under 30 seconds; optimization may take 1–2 minutes depending on page complexity. ### Option B: Webhooks Configure a webhook URL for your brand and receive HTTP callbacks at each stage transition. Configure webhooks and verify signatures. *** ## 3. Handle stage transitions ### Audit → Optimizing ```json theme={null} { "orchestration_status": "optimizing", "result": { "access_controls_score": 100, "content_delivery_score": 90, "content_quality_score": 85 } } ``` ### Optimizing → Deploying ```json theme={null} { "orchestration_status": "deploying", "optimization_run_id": "01JOPTRUN0000000000000" } ``` ### Deploying → Completed ```json theme={null} { "orchestration_status": "completed", "axp_version_id": 42 } ``` *** ## 4. Handle errors | Prefix | Stage | | --------------- | -------------------- | | `ORCH-INIT-*` | Request validation | | `ORCH-AUDIT-*` | Page audit | | `ORCH-OPT-*` | Content optimization | | `ORCH-DEPLOY-*` | AXP deployment | | `ORCH-HOOK-*` | Webhook delivery | | Code | Cause | Fix | | ----------------- | -------------------------------------------- | ---------------------------------------------------------- | | `ORCH-INIT-004` | URL domain doesn't match the registered site | Ensure all URLs belong to the site's domain | | `ORCH-AUDIT-002` | Page fetch failed (404, timeout, blocked) | Verify the URL is accessible and not blocked by robots.txt | | `ORCH-OPT-002` | No content available to optimize | Ensure the page has substantial text content | | `ORCH-DEPLOY-002` | Site not found for the given site\_id | Verify the site\_id is correct and belongs to your brand | *** ## 5. Full working example ```python theme={null} import requests import time API_KEY = "your-api-key" BRAND_ID = 1234 SITE_ID = "01JEXAMPLE00000000000000" BASE = f"https://api.scrunchai.com/v2/orchestration/optimize-and-deploy/{BRAND_ID}" HEADERS = {"Authorization": f"Bearer {API_KEY}"} urls = [ "https://example.com/page-a", "https://example.com/page-b", "https://example.com/page-c", ] resp = requests.post(BASE, headers=HEADERS, json={ "urls": urls, "optimize": True, "deploy_axp": True, "site_id": SITE_ID, }, timeout=30) resp.raise_for_status() pipeline = resp.json() print(f"Pipeline started: {pipeline.get('pipeline_id')}") pending = {r["token"]: r["url"] for r in pipeline["tokens"]} while pending: for token in list(pending.keys()): status = requests.get(f"{BASE}/{token}", headers=HEADERS, timeout=30).json() stage = status["orchestration_status"] if stage in ("completed", "failed"): result = "OK" if stage == "completed" else "FAILED" print(f" [{result}] {pending[token]}") if status.get("axp_version_id"): print(f" AXP version: {status['axp_version_id']}") del pending[token] if pending: time.sleep(5) ``` *** ## 6. Viewing results in the Scrunch dashboard Everything the pipeline does is visible in the Scrunch dashboard — exactly as if each step had been performed manually. * **Site Audit results** — **Your Brand → Site Audits** * **Content Optimizer results** — **Your Brand → Optimizer → History** * **AXP deployments** — **Your Brand → AXP → \[site] → Version History** To roll back a deployment, use the **Redeploy** option on any previous version in the AXP version history. *** ## Best practices * **Use webhooks for production** — more efficient and lower latency than polling * **Handle partial failures** — in a batch, some URLs may succeed while others fail; check each token individually * **Set `override_suggestions: true` carefully** — only your explicitly provided prompts and personas are used * **Start with audit-only** — validate URLs and check audit scores before committing to optimization and deployment Endpoint details, error codes, and schema reference. Event types, payload schemas, and signature verification. # Build with Scrunch Source: https://developers.scrunch.com/index Use Scrunch APIs, the MCP, or Data Studio integrations to query AI visibility data, automate configuration, and power custom reports.

Quickstart

Make your first API request and get brand presence data in minutes.

Scrunchie MCP

Connect your Scrunch data to Claude, ChatGPT, and other AI assistants — no code required.

API Reference

Explore all available endpoints for Query, Responses, Agent Traffic, and Configuration.

Data Studio

Visualize Scrunch data in pre-built Looker Studio dashboard templates.

# Connect Your CDN to Scrunch Agent Traffic Source: https://developers.scrunch.com/integrations/agent-traffic Stream AI crawler and bot access logs from supported CDNs and hosting platforms into Scrunch Agent Traffic to track which pages AI bots visit and why. Scrunch Agent Traffic shows which AI crawlers are visiting your site, which pages they hit, and why they came. To enable this data, your CDN or hosting platform must expose access logs that Scrunch can classify. This page serves as the entry point for CDN setup instructions. Because each platform requires different configuration steps, the full integration guides live in our Help Center. Open Agent Traffic Setup Guides ## Overview Agent Traffic works by securely reading log data from your CDN or hosting provider. We support native integrations for several major platforms, along with recommended workarounds when providers do not expose request logs directly. Supported platforms include: * Modern CDNs * Serverless hosting providers * Enterprise-grade logging platforms The exact list of supported integrations may change as we continue expanding platform coverage. Always refer to the Help Center for the most up-to-date instructions. ## What You'll Find in the Help Center Our Help Center includes: * Step-by-step setup instructions for each supported CDN or hosting provider * Code snippets where applicable (for Workers, Logpush, Vercel drains, etc.) * Required fields and log formats * Validation steps to confirm logs are flowing into Scrunch * Workarounds for platforms that do not provide direct log access Each integration guide walks you through enabling Scrunch in just a few minutes. ## Typical CDN Options While the full list is maintained in the Help Center, Scrunch includes integrations for: * Popular serverless edge platforms * Enterprise-level CDN logging products * Hosting environments used by agencies and mid-market teams * Workarounds for CMSs or hosting tools with limited log visibility These options ensure that nearly all Scrunch customers—regardless of their tech stack—can enable Agent Traffic reliably. ## Where to Go From Here Find detailed instructions for your hosting provider. Need help with an unsupported CDN or advanced setup? Our team can assist. # Install the Scrunch Data Studio Connector (v2) Source: https://developers.scrunch.com/integrations/data-studio-connector Install and configure the Scrunch Data Studio v2 connector to compare up to 30 brands side by side in Looker Studio and pull in agent traffic data. # Data Studio Connector (v2) The v2 connector is built for agencies and multi-brand organizations. Connect all your brands to a single Looker Studio data source, compare visibility side by side, and optionally pull in agent traffic data — all without juggling separate connectors per brand. Screenshot 2026 05 16 At 11 57 54 AM **What's new in v2:** * **Multi-brand support** — connect 1 to 30+ brands in a single data source * **Agent Traffic data** — see which AI bots are crawling your site, how often, and where * **Comparison fields** — brand vs. competitor presence in a single chart * **Smarter caching and parallel fetching** — faster dashboards, even at scale Looking for the original single-brand connector? See the [v1 Looker Studio guide](/integrations/looker-studio). # Install the Scrunch Data Connector The connector is not yet in the public gallery. Install it directly using the link below: Open the Scrunch Data Studio Connector ## Configure Your Connection When you open the connector, you'll see a configuration screen with the following fields: Paste your Scrunch API key. You can provision one from: **Scrunch** → **Organization** → **Settings** → **API Keys** When Data Studio shows the parameter checkboxes, **do not** check **"Allow 'API Key' to be modified in reports."** This prevents your key from being exposed to report viewers. It is safe to check the override boxes for the other parameters: * Allow "Brand IDs" to be modified in reports * Allow "Site ID (optional)" to be modified in reports * Allow "Path Filter (optional)" to be modified in reports These let report viewers customize which brands and data slices they see without exposing your API key. Enter one or more brand IDs, separated by commas. For example: `46,47,48` To find a brand ID, open the brand in Scrunch and look at the URL: `https://app.scrunchai.com/org/.../b/1234/dashboard` Here, `1234` is your Brand ID. For agency dashboards, enter all client brand IDs here. The connector fetches them in parallel and labels each row with the brand name automatically. If you want agent traffic data (which AI bots are crawling your site), enter your Site ID. Leave this blank if you only need AI visibility metrics (presence, position, sentiment). You can find your Site ID in **Scrunch** → **Brand** → **Agent Traffic**. The Site ID can be quickly found in the URL → [https://app.scrunchai.com/org/](https://app.scrunchai.com/org/) ... /sites/**\{site\_id}**\ \ *If you haven't set up Agent Traffic yet, skip this for now.* Restrict agent traffic results to a specific URL path prefix (e.g., `/blog` to only see bot traffic to your blog). Leave blank to include all paths. Path Filter is your friend on high-traffic sites — narrowing a chart to one section (like `/blog/`) makes the Agent Traffic API respond much faster and helps with the timeout errors covered in the [troubleshooting guide](/integrations/data-studio-troubleshooting). Time bucketing is automatic — the connector picks daily or weekly aggregation based on whichever date dimension you put on the chart (`Date` for daily, `Date Week` for weekly). You don't need to configure it. Click **Connect** in the top right. Data Studio will load the schema and you're ready to build. ## Available Fields The connector combines fields from two Scrunch APIs. Data Studio automatically routes your chart to the right API based on which fields you use. You cannot mix Query API fields and Agent Traffic fields in the same chart. Use separate charts for each. The connector will show a clear error message if you accidentally combine them. ### Query API Dimensions | Name | Type | Semantic Type | Notes | | ---------------------------- | ------- | ---------------- | ------------------------------------------------------ | | `brand_id` | NUMBER | NUMBER | Numeric brand identifier | | `brand_name` | STRING | TEXT | Auto-resolved from Scrunch API | | `date` | STRING | YEAR\_MONTH\_DAY | | | `date_month` | STRING | YEAR\_MONTH | | | `date_week` | STRING | YEAR\_WEEK | | | `prompt_id` | NUMBER | NUMBER | | | `prompt` | STRING | TEXT | | | `source_url` | STRING | URL | | | `source_type` | STRING | TEXT | Brand, Competitor, Other | | `persona_id` | NUMBER | NUMBER | | | `persona_name` | STRING | TEXT | | | `competitor_id` | NUMBER | NUMBER | | | `competitor_name` | STRING | TEXT | | | `ai_platform` | STRING | TEXT | ChatGPT, Perplexity, Google AI Overviews, Meta, Claude | | `ai_platform_search_enabled` | BOOLEAN | BOOLEAN | | | `tag` | STRING | TEXT | | | `branded` | BOOLEAN | BOOLEAN | Whether the prompt includes brand name(s) | | `stage` | STRING | TEXT | | | `prompt_topic` | STRING | TEXT | | | `country` | STRING | TEXT | | ### Query API Metrics | Name | Type | Semantic Type | Notes | | -------------------------------- | ------ | ------------- | ---------------------------------------------------- | | `responses` | NUMBER | NUMBER | Count of AI responses | | `brand_presence_percentage` | NUMBER | PERCENT | Share of AI responses where your brand was mentioned | | `brand_position_score` | NUMBER | NUMBER | Range: 1-100 | | `brand_sentiment_score` | NUMBER | NUMBER | Range: 1-100 | | `competitor_presence_percentage` | NUMBER | PERCENT | Requires a competitor dimension | Looking for a brand citation rate? The dedicated field was removed because it duplicated `brand_presence_percentage`. To compute the true share of responses where your brand appears as a *source URL*, see [How to track brand citation rate](/integrations/data-studio-troubleshooting#how-to-track-brand-citation-rate) in the troubleshooting guide. ### Comparison Fields These virtual fields let you compare brand and competitor presence in a single chart. When you add `entity_name` as a breakdown dimension, the connector automatically splits each row into a brand row and a competitor row. | Name | Type | Semantic Type | Notes | | --------------------- | ------ | ------------- | ----------------------------------------------------------------- | | `entity_name` | STRING | TEXT | Brand name or competitor name | | `entity_type` | STRING | TEXT | "Brand" or "Competitor" — use to filter or color-code | | `presence_percentage` | NUMBER | PERCENT | Unified presence metric (brand or competitor depending on entity) | To build a brand vs. competitor comparison chart: use `entity_name` as your dimension, `presence_percentage` as your metric, and optionally filter or color by `entity_type`. ### Agent Traffic Dimensions These fields are only available when a Site ID is configured. | Name | Type | Semantic Type | Notes | | -------------- | ------ | ---------------- | ------------------------------------------------------------------------------------------------------------- | | `date` | STRING | YEAR\_MONTH\_DAY | Daily aggregation. Use this for daily charts. | | `date_week` | STRING | YEAR\_WEEK | Weekly aggregation. Use this for weekly charts — the connector switches the API to weekly mode automatically. | | `site` | STRING | TEXT | The site being crawled | | `path` | STRING | TEXT | URL path. On high-traffic sites, pair with a Path Filter to keep queries fast (see troubleshooting). | | `agent_source` | STRING | TEXT | Bot identifier (e.g., GPTBot, ClaudeBot). High cardinality — keep date ranges short on busy sites. | | `agent_type` | STRING | TEXT | Category of agent (training, retrieval, indexer) | Monthly aggregation isn't available for agent traffic data yet. Use `Date Week` for the closest equivalent. ### Agent Traffic Metrics | Name | Type | Semantic Type | Notes | | ---------------- | ------ | ------------- | ------------------ | | `agent_requests` | NUMBER | NUMBER | Number of requests | ## Multi-Brand Dashboards The v2 connector is designed for comparing brands side by side. Here are some tips: * **Use `brand_name` as a dimension** to break down any metric by brand * **Use `brand_id` for filtering** when you want to isolate a specific brand in a chart * **Comparison fields** (`entity_name`, `entity_type`, `presence_percentage`) work per-brand — each brand's competitors are included automatically Brand names are automatically resolved from your Scrunch organization. If you see numeric IDs instead of names, make sure your API key has access to the brands you've configured. # Data Studio Dashboard Templates for Scrunch Source: https://developers.scrunch.com/integrations/data-studio-templates Copy pre-built Looker Studio dashboards for multi-brand visibility, single-brand performance, and AI agent traffic and connect them to your Scrunch data. # Dashboard Templates Choose a pre-built template to get started quickly. Make a copy and connect it to your Scrunch data source. Multi-brand visibility overview with presence, position, and sentiment. Deep dive into a single brand's visibility, sentiment, and competitive performance. See which AI bots are crawling your site, how often, and which pages they target. Measure human referral traffic to your site from AI sources like chatgpt.com and perplexity.ai. ## How to Use a Template Make sure you've already installed and configured the v2 connector. See the [Data Connector](/integrations/data-studio-connector) guide. Select a template from the gallery above and open it. In the top-right corner, click the **three dots** → **Make a copy**. When prompted, select the Scrunch data source you configured earlier. source configuration You can now modify charts, add filters, or blend additional data sources like GA4, CRM data, or paid media. Image # Troubleshoot the Scrunch Data Studio Connector Source: https://developers.scrunch.com/integrations/data-studio-troubleshooting FAQs, error fixes, and reset instructions for the Scrunch Data Studio connector covering brand IDs, agent traffic charts, date grouping, and auth issues. # Troubleshooting This page covers the issues we hear about most often when customers connect Scrunch data to Looker Studio (formerly Data Studio). It's written for marketing teams, not engineers — but every section ends with enough detail to share with a developer or paste into an AI assistant if you get stuck. If you hit an error inside a chart, the message itself tells you what to do. Each one ends with a "Diagnostic details" line you can copy and share with support or paste into Claude / ChatGPT to get more help. *** ## When a chart shows an error message The connector now surfaces real errors directly inside your chart instead of silently showing "No data." Match the message you're seeing to the right section below. #### **404, invalid values, or wrong brand data** > **Error examples**\ > You may see one or more of the following errors in a Scrunch Looker Studio report:\ > `Exception: Request failed for https://looker-api.scrunchai.com returned code 404`\ > You may also see references like: `getBrandData:236` or `getData:194`\ > Or chart-level errors such as: `Invalid values`\ > \ > **What this usually means**\ > This usually means Looker Studio is trying to request Scrunch data for a Brand ID that the connector cannot retrieve.\ > \ > Common causes include: > > 1. The data source is configured with the wrong default Brand ID. > 2. The Brand ID parameter override in the report is missing, invalid, or no longer allowed. > 3. The API key was deleted, regenerated, or rescoped through Scrunch (see [here](/getting-started/authentication)). > 4. A copied report is still pointing to a previous client’s data source or Brand ID. > 5. The connector was reconnected and the report-level or chart-level Brand ID overrides were invalidated. > > This is usually a data source / connector configuration issue as opposed to a chart design issue.\ > \ > **How to fix**\ > The person fixing this needs edit access to the Data/Looker Studio *data source*, not just the report. > > 1. Open the affected Data Studio report. > 2. Identify the Scrunch AI data source used by the broken charts. > 3. Open the Scrunch AI data source. > 4. Go to `Edit connection`. > 5. Confirm that the API key is valid. > 6. Confirm that the Brand ID(s) are correct. > 7. Confirm that the API key is scoped to **Query** and has access to the intended brand through Scrunch. > 8. If the report relies on report-level, page-level, group-level, or chart-level Brand ID overrides, make sure `Allow "Brand IDs" to be modified in reports` is checked. > 9. Click `Reconnect`. > > > Image > > > **Why Brand ID configuration matters**\ > The Scrunch Looker Studio connector pulls data for a specific Scrunch brand. During connector setup, users are prompted to enter a Brand ID, and the current connector supports pulling data for one brand at a time.\ > \ > Scrunch API tokens can be scoped to one or more brands or to an organization, but almost all API calls require a specific Brand ID. The Query API is the API used for reporting and BI workflows.\ > \ > Data/Looker Studio Community Connectors can expose overridable parameters. If the connector allows a parameter to be modified in reports, editors can override the default value at the report, page, group, chart, or control level. **"We couldn't load your agent traffic data right now…"** > This means Scrunch's Agent Traffic API returned an error for the brand(s) on this chart. Usually short-lived. > > **Try in this order:** > > 1. **Wait about a minute and refresh the chart.** Many of these errors clear on their own. > 2. **If the chart breaks down data by `Path` or `Agent Source`, shorten the date range.** Try 1 to 3 days. For high-traffic brands, those breakdowns become slow to aggregate over long ranges and can time out. > 3. **Use the connector's `Path Filter` setting** to narrow the chart to a single section of your site like `/blog/`. (See [How to edit a data source connection](#how-to-edit-a-data-source-connection) below.) > > If you keep seeing this on every refresh for the same brand even with a short date range, check whether the brand's Site ID is correct (see [Agent traffic charts won't load at all](#agent-traffic-charts-won-t-load-at-all)). **"This chart is grouping agent traffic by Path / Agent Source across a date range that's too big…"** > This is the same kind of error as above, but the connector recognized that you're using a Path or Agent Source breakdown and tailored its suggestions: > > 1. **Shorten the date range.** This is the fastest fix. Try 1-3 days first; expand from there. We've confirmed a chart breaking down \~21,000 daily agent requests by Path loads cleanly at 1 day but times out at 7 days. > 2. **Add a `Path Filter`** to scope the chart to a section. Combines well with #1. > 3. **Split one large chart into several smaller ones**, each filtered to a different section. **"We couldn't load your AI visibility data right now…"** > Same idea as the agent traffic error, but for the Query API (brand presence, citations, sentiment, etc.). Wait a minute, refresh, and if it persists, the diagnostic line in the message includes the brand ID and HTTP status — share that with support. **"This chart is asking for two kinds of data at once…"** > You've mixed brand visibility metrics (`Brand Presence`, `Brand Sentiment`, etc.) with agent traffic metrics (`Agent Requests`, `Agent Source`, etc.) in the same chart. These come from different parts of Scrunch and can't share a chart. > > **Fix:** Build a separate chart for each kind of data. One chart for the visibility metric, a second chart for the agent traffic metric. **"Agent traffic data isn't available by month yet"** > The Agent Traffic API supports daily and weekly aggregation, but not monthly. > > **Fix:** Change the chart's date dimension to `Date Week` (weekly) or `Date` (daily). **"This data source doesn't have a Scrunch API key yet"** > Click the **pencil icon** next to the data source in Looker Studio (or **Edit connection**), paste your Scrunch API key, and save. > > You can find your key at: **app.scrunchai.com → Organization → Settings → API Keys**. **"This data source needs at least one brand ID"** > Same fix path — click the pencil, then add brand IDs. Separate multiple with commas (e.g., `1234,5678,9012`). > > A brand's ID is the number after `/b/` in its Scrunch URL — e.g., `1234` in `app.scrunchai.com/org/.../b/1234/dashboard`. **"This chart uses agent traffic data, but the data source doesn't have a Site ID yet"** > See [Agent traffic charts won't load at all](#agent-traffic-charts-won-t-load-at-all) below. *** ### Charts say "No data" with no error message If the chart isn't showing an error, the connector got a successful response — there's just no data to display. Common causes: **The date range is outside the last 90 days** > Scrunch's Query API only returns data for the **last 90 days**. If your report's date range starts further back than that, your visibility charts will be empty. > > * **Fix:** Set the report or chart date range to a window within the last 90 days. The built-in "Last 30 days" / "Last 90 days" presets work well. **The chart filter is too restrictive** > A `branded = false` filter, a competitor that wasn't tracked during the date range, or a tag that doesn't exist will all return zero rows. Screenshot 2026 05 16 At 12 11 17 PM **Branded vs. non-branded prompts** > By default, the Scrunch dashboard filters to non-branded prompts. If you set up a chart with the same filter and your figure in the Scrunch app includes branded prompts (or vice versa), the numbers will look different. > > * **Fix:** Add a `Branded` filter to the chart and set it to match what you want — `false` for non-branded only, `true` for branded only, or remove the filter to include both. **The chart's per-chart data source is wrong** > Looker Studio lets every chart override the report-level data source. If a chart was copied from a template, its **per-chart data source** might still point to the original (broken) connector, even though you've already set the report-level data source correctly. > > * **Fix:** Click the chart → look in the right-hand panel under **Setup** → **Data source**. If it shows anything other than your Scrunch data source, click it and swap. Screenshot 2026 05 16 At 12 10 16 PM *** ### Agent traffic charts won't load at all > Agent traffic charts need three things to work: > > 1. A valid **API key** on the data source. > 2. One or more **brand IDs** that your API key can read. > 3. A **Site ID** for each brand whose agent traffic you want to chart. > > The first two errors above are caught and shown clearly. The third one — Site ID — is also surfaced as an error now, but if you're seeing empty charts after configuring a Site ID, double-check the value. > > **Where to find a Site ID:** > > 1. Open the brand in Scrunch. > 2. Navigate to **Agent Traffic**. > 3. Look in the URL — the Site ID is the long string after `/site/` (e.g., `01KCHAEBS552AC5G1Z454E1AG2`). > 4. Paste it into the data source's **Site ID** field. > > The Site ID must belong to a brand your API key can access. If you have multiple brands, you currently configure one Site ID per data source — if you need agent traffic for multiple brands in one report, create a second data source for each. *** ### **After making a copy of a template** > When you copy a Scrunch Looker Studio template into your own account, you'll see one or more data sources labeled **Unknown** under the report. That's expected — Looker Studio can't share the original Scrunch data source across accounts, so it shows the placeholder until you swap in your own connection. > > **Fix:** > > 1. Open the copied report. > 2. Click **Resource** → **Manage added data sources**. > > Screenshot 2026 05 16 At 12 09 16 PM > > 3. For each "Unknown" entry, click **Edit** → Looker will prompt you to pick a replacement. Choose your Scrunch data source. > 4. Save. > > Some templates have **per-chart** data sources in addition to the report-level one. After fixing the report-level data source, check a few charts — if they still show "Unknown" or "No data," edit the chart and update its data source the same way (see [The chart's per-chart data source is wrong](#the-chart-s-per-chart-data-source-is-wrong)). *** ### How to track brand citation rate > `Brand Citation (%)` was removed from the connector because it was an alias for `Brand Presence (%)` — two fields with identical values was confusing more than helping. > > If you want a true citation rate (percentage of responses where your brand shows up as a source URL), build a calculated field in Looker Studio: > > ```text theme={null} > COUNT(CASE WHEN Source Type = "brand" THEN Source URL END) / COUNT(Source URL) > ``` > > Use it in a chart with `Source Type` as a hidden filter or aggregate it across all rows for a single percentage. Set the metric type to **Percent** so Looker formats it correctly. *** ### A chart loads partly, then stops > This happens on charts pulling lots of data. Looker Studio gives the connector a fixed time budget per chart; if it runs out before all the rows arrive, the chart can render partially or skip the rest. > > **What works:** > > 1. **Set a custom date range on the chart** that's narrower than the report's range. Smaller fetch, completes in time, gets cached. > 2. **Refresh the report.** The first attempt may have failed; subsequent attempts read from cache and finish. > 3. **Avoid combining several high-cardinality breakdowns** in one chart (e.g. `Path` + `Agent Source` + `Date` together). Pick one breakdown and use filters to narrow the others. *** ### Why the same chart errored a minute ago and is error-free now (or vice versa) > When the connector hits an API error for a specific brand, it remembers that failure for **60 seconds** and returns the cached error instantly for any chart that asks for the same data during that window. This protects Scrunch's API from being hammered while it recovers and gives you fast feedback that something is still wrong. > > After 60 seconds, the connector tries again. If the underlying issue cleared, the chart loads normally. If not, you'll see the same error message. > > This is why hitting refresh repeatedly during an outage looks like nothing is happening — you're hitting the cached error each time. Wait a full minute between refreshes for the connector to retry. *** ## How to edit a data source connection If an error message tells you to "edit the data source," here's the path in Data/Looker Studio: Click **Edit** in the top right corner. Screenshot 2026 05 16 At 12 07 52 PM Click **Resource** → **Manage added data sources** Screenshot 2026 05 16 At 12 08 15 PM Find your Scrunch data source in the list and click **Edit** on the right. The connector configuration screen opens. Update the API Key, Brand IDs, Site ID, or Path Filter as needed, then click **Reconnect** in the top right. Screenshot 2026 05 20 At 10 08 25 AM When prompted, click **Apply** to push the updated configuration to all charts using this data source. *** ## How to read the diagnostic details in an error message Every connector error ends with a `Diagnostic details for reference:` block. The pieces: * `API="…"` — which Scrunch API failed (`"Query API"` or `"Agent Traffic API"`) * `brand=…` — the brand ID that returned the error * `status=…` — the HTTP status code (5xx = Scrunch backend issue, 4xx = config/auth issue) * `body="…"` — a short snippet of the API's error response * `fields="…"` — the fields the chart asked for (in newer messages; helps identify high-cardinality timeouts) If you need help, you can paste the whole error message — including the diagnostic line — into Claude or ChatGPT and they can usually point you to the cause. Or share it with Scrunch support (the diagnostic line is the most useful part). *** ## FAQs **Can I use this with just one brand?** > Yes. Enter a single Brand ID and the connector works exactly like the older single-brand connector, with the added benefit of comparison fields, agent traffic support, and clearer error messages. **Does Agent Traffic support weekly date grouping?** > Yes. Use `Date Week` as the chart's date dimension and the connector aggregates by week automatically. (Monthly is not supported by the Agent Traffic API yet.) **Are there limits to dashboard size?** > Looker Studio allows a maximum of 30 concurrent Community Connector queries. Each chart counts as one query. Reports with more than \~15-20 Scrunch-powered charts may load slowly or hit the limit. If you need a large dashboard, consider splitting it across multiple report pages — Looker only loads the visible page. **How do I compare last week vs. previous week?** > Use Looker Studio's built-in date comparison feature (in the date range control), or create a calculated field like: > > ```text theme={null} > CASE > WHEN DATE_DIFF(CURRENT_DATE(), date, DAY) < 7 THEN brand_presence_percentage > END > ``` *** ## Resetting your connector If something goes wrong and you want to start fresh: Go to [Looker Studio](https://lookerstudio.google.com/navigation/reporting) and click **Data Sources** in the top navigation. Data Sources reset Find your Scrunch data source → click the three dots → **Remove**. Screenshot 2026 05 13 At 11 40 33 PM Click **+ Create** → **Data source** → Scroll down to find the Scrunch connector under **Partner Connectors** → click the three dots → **Revoke**. Screenshot 2026 05 16 At 10 59 18 AM Screenshot 2026 05 16 At 11 00 37 AM Use the [connector install link](https://datastudio.google.com/datasources/create?connectorId=AKfycbyi7ba5UXYeYqau1m6upcPFRBm2n0z49C5fg3dSwdbdFArz2IjLbCBc05HcNsoMpLFOcQ) to start fresh. # Looker Studio Legacy Single-Brand Connector Source: https://developers.scrunch.com/integrations/looker-studio Configure the legacy single-brand Scrunch Looker Studio Community Connector to build dashboards and blend brand visibility metrics with GA4 and other sources. # Looker Studio Connector (Legacy) This is the legacy single-brand connector. For multi-brand support, agent traffic data, and comparison fields, use the [Data Studio Connector](/integrations/data-studio-connector) (formerly Looker Studio v2) Connect Scrunch to Google Looker Studio using our private Community Connector. This allows you to build dashboards, analyze historical performance, and blend Scrunch metrics with other data sources such as GA4. Hero Pn The connector exposes all standard Scrunch Query API fields, including: * Brand presence, position, and sentiment * Competitor presence metrics * Date, platform, persona, tag, and source dimensions Once connected, you can create fully custom dashboards or use our pre-built Scrunch Looker Studio template. ## Install the Scrunch Looker Studio Connector The connector is not yet in the public gallery. Install it directly using the link below: Open the Scrunch AI Looker Studio Connector This installs the Scrunch AI data source inside Looker Studio for your Google account. ## Authenticate With Your Scrunch API Key During setup, Looker Studio will prompt you for: 1. **Your API key** > You can provision a Query-scoped API key from: > > **Scrunch** → **Organization** → **Settings** → **API Keys** > > > A single API key may be scoped to one or many brands. Use narrow scoping when integrating with client-facing dashboards. > 2. **Your Brand ID** > The connector loads data for one brand at a time. > > To find your brand ID: > > Open the brand's dashboard in Scrunch > > Look at the URL: > > `https://app.scrunchai.com/org/.../b/1234/dashboard ` > > Here, 1234 is your Brand ID. > > > If you need multi-brand dashboards, reach out to Scrunch. We are collecting feedback for expanded multibrand support. > ## Supported Dimensions and Metrics ### Dimensions The connector aligns with the Scrunch Query API. | Name | Data Type | Semantic Type | Notes | | ---------------------------- | --------- | ---------------- | ------------------------------------------------------ | | `prompt_id` | NUMBER | NUMBER | | | `prompt` | STRING | TEXT | | | `date_month` | STRING | YEAR\_MONTH | Last 90 days of data | | `date_week` | STRING | YEAR\_WEEK | Last 90 days, keep filters week-aligned | | `date` | STRING | YEAR\_MONTH\_DAY | Last 90 days of data | | `source_url` | STRING | URL | | | `source_type` | STRING | TEXT | Brand, Competitor, Other | | `persona_id` | NUMBER | NUMBER | | | `persona_name` | STRING | TEXT | | | `competitor_id` | NUMBER | NUMBER | | | `competitor_name` | STRING | TEXT | | | `ai_platform` | STRING | TEXT | ChatGPT, Perplexity, Google AI Overviews, Meta, Claude | | `ai_platform_search_enabled` | BOOLEAN | BOOLEAN | | | `tag` | STRING | TEXT | | | `branded` | BOOLEAN | BOOLEAN | Whether prompt includes brand name(s) | ### Metrics | Name | Data Type | Semantic Type | Notes | | -------------------------------- | --------- | ------------- | ----------------------------- | | `responses` | NUMBER | NUMBER | Count | | `brand_presence_percentage` | NUMBER | PERCENT | | | `brand_position_score` | NUMBER | NUMBER | Range: 1–100 | | `brand_sentiment_score` | NUMBER | NUMBER | Range: 1–100 | | `competitor_presence_percentage` | NUMBER | PERCENT | Requires competitor dimension | There is currently no singular metric that recreates the Scrunch `Competitive Benchmark `visualization. You may create side-by-side charts or blend data sources to approximate the view. ## Using the Scrunch Looker Studio Template To accelerate setup and reporting, Scrunch provides a pre-built template. Click the template link. In the top-right corner, click the **three dots** → **Make a copy**. Be sure to add install the [Scrunch Looker Studio Connector](https://lookerstudio.google.com/datasources/create?connectorId=AKfycbzRRK2rRqh1_ujHS313hitMb5PopzgNUS5m5ih6ohI) prior to copying. Copy Pn When prompted, select the Scrunch AI Looker Studio connector you configured earlier. Data Pn You can now modify charts, add filters, or blend additional sources like GA4, CRM data, paid media, and more. ## FAQs **How do I compare last week vs. previous week?** > Create custom metrics inside Looker Studio using conditional date filters. Example: > > * Last 7 days > * Same 7 days previous period > * Month-to-date vs prior month-to-date > > Looker Studio supports calculated fields using functions like: > > ```text theme={null} > CASE > WHEN DATE_DIFF(CURRENT_DATE(), date, DAY) < 7 THEN brand_presence_percentage > END > ``` **Are there limits to dashboard size?** > Yes. Looker Studio allows a maximum of 30 concurrent Community Connector queries. Dashboards with more than \~15 Scrunch-powered charts may hit this limit depending on complexity. **How do I recreate the Brand Presence + Competitor Presence chart from the Scrunch dashboard?** > A version of this combined view is already included in the Scrunch Looker Studio template. When you make a copy of the template, zoom out on the canvas—you’ll see a hidden chart that mimics the dual-line Brand vs. Competitor Presence visualization from the Scrunch dashboard. > > Looker Studio does not natively blend these metrics into a single field, so the chart requires custom-calculated metrics under the hood. Each competitor’s presence must be defined using a conditional formula, such as: > > ```text theme={null} > CASE WHEN competitor_name = "Competitor A" THEN competitor_presence_percentage END > ``` > > **To customize the benchmark view for your own competitive set:** > > 1. Open the hidden chart in your copied template > 2. Edit each metric formula > 3. Replace the competitor names with the ones relevant to your brand > > > There is no universal “competitive benchmark” metric available from the API. The Looker Studio template replicates this view by combining multiple calculated fields inside one chart. > > > Alt Chart Pn ## Resetting Your Connector (If Needed) If the connector was set up incorrectly, here's how to completely reset it: Visit: [https://lookerstudio.google.com/navigation/reporting](https://lookerstudio.google.com/navigation/reporting) Click Data Sources in the top navigation. Find your Scrunch connector → ⋮ → Remove Data Source Pn This could be named "**AI Data Connector**." Click + Create → Data source → Partner Connectors → Scrunch AI Then ⋮ → Revoke Delete Pn Use the connector link again: [https://lookerstudio.google.com/datasources/create?connectorId=AKfycbzRRK2rRqh1\_ujHS313hitMb5PopzgNUS5m5ih6ohI](https://lookerstudio.google.com/datasources/create?connectorId=AKfycbzRRK2rRqh1_ujHS313hitMb5PopzgNUS5m5ih6ohI) You now have a clean state. ## Summary Build dashboards for brand trends, sentiment, competitors, and platform performance. Unify Scrunch visibility metrics with site traffic and conversion data. Use our prebuilt Looker Studio template to jumpstart reporting. # Meet Scrunchie Source: https://developers.scrunch.com/mcp/overview Connect your Scrunch data to Claude, ChatGPT, and other AI assistants. Ask questions in plain English and get answers from your live data. Scrunch MCP banner The Scrunch MCP lets you query your brand monitoring data directly inside Claude, ChatGPT, Microsoft Copilot, and other AI assistants - no API key, no code, no dashboard switching. You authenticate once with your Scrunch account, and from then on your assistant can answer questions like "How has our presence trended this quarter?" or "Which competitors are winning on Perplexity?" using your live data. *** ## What you can do Filter and Pull your Scrunch data like presence, position, sentiment, and citations across AI platforms. Create and update brands, competitors, personas, and prompts all in one natural language conversation. Import AI agent crawl logs from a CSV and query which AI crawlers are hitting your site, how often, and on which pages. Migrate your brands, prompts, personas, tags, alternative names, and competitors into Scrunch with one export prompt and one import prompt. Works whether your current tool has an MCP, CSV export, or just a settings page you can copy from. *** ## How it works Add the Scrunch MCP server to your AI client of choice. Your assistant redirects you to Scrunch's normal sign-in flow — no shared secrets or API keys to manage. [See the setup guide →](/mcp/setup) Start a conversation and ask about your brand. Your assistant automatically selects the right Scrunch features, resolves your brand ID, and anchors date ranges like "last 30 days" to today's date before querying. Responses are grounded in your actual Scrunch data — your brands, your competitors, your prompts, your metrics. You can ask follow-up questions, request comparisons, and have the assistant draft summaries or slide copy based on what it finds. *** ## What you need **Prerequisites** * A Scrunch account (any plan). Your existing brand permissions carry over automatically. * A compatible AI client: Claude (Free, Pro, Max, Team, or Enterprise), ChatGPT (Plus, Pro, Team, Enterprise, or Edu — Developer Mode required), Microsoft Copilot Studio, Cursor, VS Code, or Windsurf. * About 5 minutes to complete the setup. *** ## Known limitations Most of what's in the Scrunch dashboard is available through MCP, but a few things aren't accessible yet: 1. **Cited pages and URL detail** — Aggregate citation metrics show the overall split between brand-owned, competitor, and third-party sources, but not which specific URLs are being cited. Individual citation URLs are available on raw responses via the `list_responses` feature. 2. **Sitemap and Page Audit data** — Not currently available via MCP. It will be available in a future update. 3. **Accounts with many prompts** — Results are capped at 1,000 records per request. If you manage a large number of prompts, filter by tag or date range to stay within this limit. *** ## Get started Connect the Scrunch MCP to Claude, ChatGPT, Copilot Studio, Cursor, VS Code, or Windsurf. Takes about 5 minutes. Multi-tool workflows that combine Scrunch with Notion, Slack, and other AI apps — copy-paste ready. 35+ ready-to-copy prompts for visibility analysis, competitive intelligence, reporting, and configuration. Everything available via MCP, with descriptions and example prompts. # Citation Analysis Source: https://developers.scrunch.com/mcp/prompts/citation-analysis Find which pages AI is citing from your site, which topic areas get skipped, and which third-party sources are driving your mentions. Citations tell you what AI is actually reading to talk about \[brand name]. These prompts show you which owned pages are working, which aren't being used despite being relevant, and which third-party sources have the most influence. *** How often is AI citing \[brand name]'s own content — and which topic areas have zero citations? ```text theme={null} For [brand name], pull prompt variants filtered to citation_domain = [brand domain] (e.g., "brandname.com"). Report: 1. How many variants cite [brand domain]? 2. What percentage of total tracked variants does this represent? 3. What tags and topics are the cited variants concentrated in? 4. Are there tags with zero or near-zero citations from [brand domain]? Those are content citation gaps. ``` Topic areas where AI is answering questions but not pulling from \[brand name]'s pages — even when those pages exist. ```text theme={null} For [brand name], run a citation coverage analysis. For each major tag in the brand's configuration: 1. Pull variants with that tag where citation_domain = [brand domain] — count 2. Pull total variants with that tag — count 3. Calculate citation rate per tag Rank tags by citation rate from lowest to highest. Tags with low citation rates despite having tracked prompts are content gaps — AI is answering these questions but not citing [brand name]'s content. ``` Which competitor domains is AI pulling from — and on which topics are they getting cited instead of \[brand name]? ```text theme={null} For [brand name], I want to see which competitor domains are being cited in AI responses. Run pulls filtered to citation_domain for each main competitor's domain: - citation_domain = [competitor1.com] - citation_domain = [competitor2.com] - citation_domain = [competitor3.com] For each, report the count and which tags/topics they're concentrated in. Which competitor's content is AI pulling from most? On which topics is their content being cited instead of [brand name]'s? ``` When \[brand name] appears in AI responses via third-party sources, which sites are responsible? These are the highest-leverage PR and partnership targets. ```text theme={null} For [brand name], pull variants where: - brand_present = true - citation_domain is NOT [brand domain] (i.e., [brand name] is mentioned but via third-party sources) Limit to 30 results. What third-party domains are responsible for [brand name]'s AI mentions? Are there publications, directories, or review sites that AI consistently uses to reference [brand name]? These are the highest-leverage third-party PR and link targets. ``` *** Find the topic areas where neither \[brand name] nor competitors are showing up yet. Full workflow: gap analysis into a Notion tracker with content recommendations. # Competitive Intelligence Source: https://developers.scrunch.com/mcp/prompts/competitive-intel MCP prompts to rank competitors by AI share of voice, identify where rivals are displacing your brand, and surface positions you need to protect in AI search. These prompts compare \[brand name] against every tracked competitor — from a full share of voice ranking to a detailed head-to-head on the specific prompts you're losing. *** Which competitors appear most often across \[brand name]'s tracked prompts — and how dominant are they? ```text theme={null} For [brand name], first list all configured competitors to get their IDs. Then for each competitor, pull the count of variants where competitor_present = [competitor ID]. Build a competitor presence ranking: which competitors appear most frequently in AI responses across [brand name]'s tracked prompts? Calculate each competitor's presence rate vs. total variants. Rank them. Flag any competitor appearing in more than 30% of prompts — that's a dominant player worth analyzing further. ``` The specific prompts where \[competitor name] shows up and \[brand name] doesn't — direct displacement, ranked by observation count. ```text theme={null} For [brand name], get the competitor ID for [competitor name] from the competitors list. Then pull variants filtered to: - competitor_present = [competitor ID] - brand_present = false Limit to 50 results. This shows prompts where [competitor name] appears in AI responses but [brand name] does not. For this set: 1. What topics or categories are these? Tag/topic breakdown 2. Are these branded or unbranded queries? 3. What is [competitor name] likely doing well that [brand name] isn't for these queries? 4. Which of these represent the most valuable queries to reclaim — highest observation count, most commercially relevant topics? ``` For every competitor: how many prompts do they win outright vs. share with \[brand name]? ```text theme={null} For [brand name], list all competitors and get their IDs. For each competitor, run two counts: 1. competitor_present = true, brand_present = false → competitor wins, brand loses 2. competitor_present = true, brand_present = true → both appear (co-mentions) Build a displacement table showing for each competitor: how many prompts they win outright vs. share. Rank competitors by displacement rate. The top competitors are actively taking visibility that [brand name] should own. ``` The prompts where \[brand name] appears and top competitors don't — the territory to protect and expand. ```text theme={null} For [brand name], pull variants where brand_present = true. Within this set, identify which prompts are non-branded (branded = false) — these are category queries where [brand name] is earning unprompted AI visibility. Separately, for the top 3 competitors by presence rate, check their presence on the same prompts using competitor_present filter. Identify prompts where [brand name] appears and those competitors do not — these are [brand name]'s defensible positions. ``` *** Full workflow: complete SOV ranking with displacement map and optional Slack post. See which competitor pages AI is citing — and which of yours aren't getting cited. # Configuration & Maintenance Source: https://developers.scrunch.com/mcp/prompts/configuration Audit your Scrunch setup, find duplicate prompts, check platform coverage, standardize tags, and clean up stale configuration with conversational MCP prompts. A clean configuration produces accurate data. Use these prompts to audit your setup before a reporting cycle, clean up stale or duplicate prompts, and ensure your tag structure stays consistent as brands and teams grow. *** Are the right competitors, tags, and prompts in place? Flag gaps that would skew your visibility data. ```text theme={null} For [brand name], run a full configuration audit: 1. List all competitors — are any major players missing from the industry? 2. Get all tags — do the tags represent the full scope of how buyers research this category? 3. Pull total variant count — are there enough prompts to generate statistically meaningful data? 4. Pull branded = true variant count — do branded queries make up a reasonable share of tracking? 5. Pull branded = false variant count — are enough unbranded category queries being tracked? Flag any gaps in configuration that would skew the visibility data. ``` Identify near-duplicate prompts within a tag group before they inflate counts and distort visibility rates. ```text theme={null} For [brand name], pull all seed prompts tagged as [tag name]. Review the prompt text for duplicates, near-duplicates, or prompts so similar they're tracking the same query twice. List candidates for archiving. Do not archive anything without my confirmation. ``` Are any prompts running on some platforms but not others when they should be everywhere? ```text theme={null} For [brand name], pull seed prompts and their variant_scenarios field. Identify any seed prompts that are not running on all platforms (e.g., running on ChatGPT and Perplexity but not Gemini or Grok). List these coverage gaps by seed prompt. Flag whether the missing platform coverage appears intentional or like an oversight. ``` Find orphaned tags, overlapping names, and uncategorized prompts — then get a recommended structure. ```text theme={null} Get all tags for [brand name]. Identify: 1. Tags with fewer than 5 prompts — likely orphans or misfiled 2. Tags whose names overlap in meaning (e.g., "competitors" vs. "alternatives" vs. "compare") 3. Tags with no clear category alignment Suggest a consolidated tag structure. Then, for any tag with fewer than 5 prompts, list those prompts so I can decide whether to reassign them. ``` Establish a Day 1 reading for a brand that just went live, to compare every future report against. ```text theme={null} For [brand name], establish a baseline reading now that the brand just went live in Scrunch. 1. Pull total variant count and confirm data has started collecting (variants should show non-zero observation counts within 24-48 hours of setup) 2. Get presence, position, and sentiment metrics for the data collected so far 3. List all tags and confirm prompts are distributed across them as expected Present this as a "Day 1" baseline I can compare all future reports against. Flag anything that looks like it isn't collecting data yet. ``` Platform coverage isn't the only gap worth checking — confirm prompts span the full buying journey too. ```text theme={null} For [brand name], check whether our tracked prompts actually cover the full buying journey, not just one stage. 1. Get all tags and identify which represent funnel stages (awareness, consideration, decision) versus topic/product tags 2. Pull variant counts for each funnel-stage tag 3. Flag if any stage is significantly under-tracked relative to the others (e.g., dozens of awareness-stage prompts but almost no decision-stage prompts) Recommend which funnel stage most needs new prompts added, and roughly how many. ``` *** Starting from scratch? Configure a brand, competitors, and prompts in a single chat. See everything available via MCP with descriptions and example prompts. # Platform-Specific Analysis Source: https://developers.scrunch.com/mcp/prompts/platform-analysis MCP prompts that compare brand visibility on ChatGPT, Perplexity, Gemini, and Google AI Overviews to find which platform is underperforming and why. ChatGPT, Perplexity, Gemini, and Google AI Overviews don't behave the same way. Use these prompts to find where \[brand name] underperforms on specific platforms and what's different about the queries it's losing there. *** Visibility rates ranked by platform — plus the specific prompts driving the worst performance. ```text theme={null} For [brand name], run the following analysis for each major platform (chatgpt, perplexity, claude, gemini, grok, meta): - Total variants on that platform - brand_present = true count on that platform - brand_present = false count on that platform - Visibility rate per platform Rank platforms by visibility rate. For the two lowest-performing platforms, pull 10 example prompts where brand_present = false to show what types of queries [brand name] is missing there. ``` What is \[brand name] consistently missing on one particular platform? Are the gaps topic-specific? ```text theme={null} For [brand name], pull prompt variants filtered to: - platform = [platform name] - brand_present = false Limit to 30 results sorted by observation_count descending. What is [brand name] consistently missing on [platform name]? Are the gaps concentrated in specific topics or tags? Is there a pattern to what [platform name] tends to surface vs. what [brand name] provides? ``` Prompts where \[brand name] appears on ChatGPT but not Perplexity (or vice versa) — these inconsistencies reveal platform-specific optimization opportunities. ```text theme={null} For [brand name], I want to find prompts where [brand name] appears on some platforms but not others. Pull variants where brand_present = true for platform = chatgpt. Then pull brand_present = false for the same tag set on platform = perplexity. Compare the overlap — identify seed prompts where ChatGPT cites [brand name] but Perplexity doesn't (or vice versa). These inconsistencies reveal platform-specific optimization opportunities. ``` *** Get the full cross-platform visibility picture before drilling into a specific platform. See which content is being cited on each platform and where the gaps are. # Rankings & Priority Lists Source: https://developers.scrunch.com/mcp/prompts/rankings MCP prompts that return ranked top-10 and bottom-10 lists of best performing prompts, biggest missed opportunities, and weakest topic areas for triage. These prompts produce ranked lists optimized for two jobs: sharing the wins with stakeholders and triaging where to act next. Each one returns a top-10 or bottom-10 view sorted by observation count or visibility rate. *** The highest-visibility prompts — what's driving them, and what do they have in common? ```text theme={null} For [brand name], pull prompt variants filtered to brand_present = true. Sort by observation_count descending. Return the top 10. For each: - Show the seed prompt text - Show the platform - Show the observation count - Note whether it's branded or unbranded - Note the tag/topic Summarize: what do [brand name]'s best-performing prompts have in common? Topic, framing, funnel stage? ``` The most-observed queries where \[brand name] is absent — ranked by how much it matters. ```text theme={null} For [brand name], pull prompt variants filtered to brand_present = false. Sort by observation_count descending. Return the top 10. For each: - Show the seed prompt text - Show the platform - Show the observation count - Note whether it's branded or unbranded - Note which competitors appear instead (if any) Prioritize: which of these 10 gaps represents the most urgent fix, and why? ``` The highest-observation prompts where \[competitor name] appears and \[brand name] doesn't — what to fix first. ```text theme={null} For [brand name], get the competitor ID for [competitor name]. Pull variants filtered to: - competitor_present = [competitor ID] - brand_present = false Sort by observation_count descending. Return top 10. These are the highest-stakes losses — prompts where [competitor name] is getting the AI mention and [brand name] isn't. For each, identify what content [brand name] would need to create or optimize to compete. ``` The owned pages that AI cites most often — understand what makes them work so you can replicate it. ```text theme={null} For [brand name], pull variants filtered to citation_domain = [brand domain]. Sort by observation_count descending. Return top 10. These are the prompts where [brand name]'s own content is getting cited most by AI. Note which pages are cited and what topics they cover. These are the pages to protect, expand, and use as a model for other content. ``` Tag groups with the lowest visibility rate — combining gap size and observation volume into a single priority score. ```text theme={null} For [brand name], get all tags. For each tag, pull: - Total variant count for that tag - brand_present = true count for that tag Calculate visibility rate per tag. Return the 10 tags with the lowest visibility rate. Rank by urgency: low visibility rate combined with high observation count = highest priority. ``` *** Package these rankings into a pre-call brief, monthly digest, or QBR summary. Full workflow: pull all the data and have Claude write and save the complete report. # Reporting Digests Source: https://developers.scrunch.com/mcp/prompts/reporting MCP prompts that generate structured monthly digests, QBR slides, client call prep docs, and onboarding briefs ready to drop into a presentation. These prompts produce complete, structured reports — not raw data. Each one is designed to go directly into a client presentation, stakeholder update, or call prep doc with minimal editing. *** A complete month-in-review, structured for sharing with clients or leadership. ```text theme={null} For [brand name], build a monthly AI visibility digest. Pull: 1. Total tracked variants — count 2. brand_present = true — count → calculate overall visibility rate 3. brand_present = true by platform — count per platform 4. brand_present = false sorted by observation_count, top 10 — the month's biggest gaps 5. Competitor presence counts for top 3 competitors 6. Tags with lowest visibility rate — top 5 gap tags Organize into this structure: - Visibility Score: [X]% overall, with platform breakdown - Top Performing Areas: where brand presence is strongest - Priority Gaps: top 10 missing prompts by observation volume - Competitive Snapshot: competitor presence rates - Recommended Actions: 3 specific items for the next 30 days ``` The starting-point snapshot for a new brand — configuration health, current visibility, and first priorities. ```text theme={null} I'm establishing a baseline for [brand name] in Scrunch. Run the following: 1. List all competitors — count and names 2. Get all tags — count and names 3. Total tracked variants — count 4. brand_present = true — count → overall visibility rate 5. branded = true, brand_present = false — count → branded query gaps (should be near zero) 6. brand_present = false, top 5 by observation_count — the most critical current gaps Deliver as a baseline report with: - Configuration Health: are the right competitors and tags set up? - Current Visibility Rate: overall and by platform - Immediate Gaps: branded queries where [brand name] isn't appearing - Top 5 Priorities for the first 90 days ``` Five talking points before a client or stakeholder call — just the numbers that matter, nothing else. ```text theme={null} I have a call with [brand name] in [X] minutes. Give me a quick brief. Pull: 1. Overall visibility rate (brand_present = true / total) 2. Best platform and worst platform by visibility rate 3. Top 3 prompts by observation count where brand_present = false — the headline gaps 4. Any branded queries where brand_present = false — urgent issues to flag Give me 5 key talking points I can use in the call. One sentence each, lead with the number. Keep it tight — I need something I can scan in 2 minutes. ``` Full QBR structure: performance, competitive position, content gaps, and next quarter's focus. ```text theme={null} For [brand name], build a quarterly business review summary for AI visibility. Pull and analyze: 1. Overall visibility rate vs. benchmark (brand_present=true rate vs. total) 2. Platform breakdown — visibility rate per LLM 3. Top 5 tags by visibility rate (strengths) 4. Bottom 5 tags by visibility rate (gaps) 5. Competitive displacement — for each tracked competitor, how many prompts do they appear in where [brand name] does not? 6. Top 3 citation domains (brand's own domain + top 2 competitor domains) Structure as: Performance Summary → Competitive Position → Content Gaps → Recommended Next Quarter Focus ``` *** Full workflow: Claude pulls all the data, writes the report, and saves it to Notion. Keep stakeholders updated between monthly reports with an automated weekly brief. # Sentiment Signals Source: https://developers.scrunch.com/mcp/prompts/sentiment-signals MCP prompts that go beyond the presence question to check how AI assistants actually talk about your brand — positive, mixed, or negative — and why. Being mentioned isn't the same as being spoken about well. These prompts focus specifically on `get_sentiment_metrics` and the response text behind it, to answer not just "are we present" but "how are we described when we are." *** A quick read on how AI assistants currently talk about the brand, and whether that's shifting. ```text theme={null} For [brand name], get sentiment metrics for the last 30 days, and again for the 30 days before that. Show the positive/mixed/negative split for both periods and the change. Break it down by AI platform — is sentiment consistent across ChatGPT, Perplexity, Gemini, and Google AI Overviews, or is one platform notably more critical? Summarize in one sentence: is sentiment improving, holding steady, or declining? ``` Not just "are we positive" — positive relative to who. ```text theme={null} For [brand name], get sentiment metrics for the last 30 days for [brand name] and [competitor name] side by side. Compare the positive/mixed/negative split for both brands. If one brand is described more favorably, pull 2-3 example prompts that illustrate the gap. ``` Don't just see the negative percentage — read what's actually being said. ```text theme={null} For [brand name], get sentiment metrics for the last 30 days filtered to negative sentiment only. List the specific prompts and platforms where this occurred. For the 3 highest-observation prompts, pull the full response text with get_response. What specific claim, comparison, or complaint is driving the negative read? Is it the same issue repeating across responses, or several unrelated ones? ``` *** Pair sentiment with the presence numbers for the fuller picture of how the brand shows up. Extend the sentiment comparison prompt to your full tracked competitor set. # Trends & Alerts Source: https://developers.scrunch.com/mcp/prompts/trends-and-alerts MCP prompts that frame metrics over time — what changed since last period, what's been quietly sliding, and what's crossed a threshold worth flagging. A single snapshot can hide a slow decline or overstate a one-off spike. These prompts are built around comparison — this period against last, or against a threshold you set — so movement gets caught early instead of showing up as a surprise in the monthly report. *** A fast before/after read across every core metric. ```text theme={null} For [brand name], compare the last 30 days against the 30 days before that for presence, position, sentiment, and citation metrics. For each metric, show the change and call out which one moved the most — in either direction. Give me a one-paragraph summary of the month's biggest story. ``` A single bad month can be noise. Three in a row is a trend. ```text theme={null} For [brand name], get presence metrics for each of the last 3 months separately (not combined). Identify any tag or platform where presence has declined in each of the 3 consecutive months, even if each individual drop looks small. A steady 3-month decline is worth flagging even if no single month looks alarming on its own. ``` Skip the full review — just tell me if something crossed a line. ```text theme={null} For [brand name], check whether any of the following happened in the last 7 days: - Presence rate dropped more than [5] percentage points vs. the prior 7 days - Sentiment (positive share) dropped more than [5] percentage points - Any tracked competitor's share of voice increased more than [10] percentage points - Citation share to [brand domain] dropped more than [5] percentage points If nothing crossed a threshold, just say so in one line. If something did, tell me exactly what and by how much — no other commentary needed. ``` *** Automate the threshold-check prompt above into a recurring Slack post. Roll a monthly trend read into a structured digest for stakeholders. # Visibility Gaps & Content Opportunities Source: https://developers.scrunch.com/mcp/prompts/visibility-gaps MCP prompts that find topics where your brand is absent from AI responses, rank gaps by urgency, and group them into actionable content opportunities. These prompts surface where \[brand name] isn't showing up and help you understand why. Use them before a content planning session or when you need to identify where to invest next. *** Which topic areas have the worst visibility? Ranked by gap rate so you know where to invest first. ```text theme={null} For [brand name], get all tags from the Scrunch configuration. For each tag, pull: - Total variants with that tag - Variants with that tag where brand_present = false Calculate a "gap rate" per tag (brand absent / total). Rank tags by gap rate from highest to lowest. The top tags are the highest-priority content investment areas. Show me the top 10 gap tags and list 5 example prompts from each of the top 3. ``` Unbranded, category-level queries where \[brand name] is invisible — clustered into actionable themes. ```text theme={null} For [brand name], pull prompt variants filtered to: - branded = false (unbranded category or comparison queries) - brand_present = false Limit to 50 results sorted by observation_count descending. For this set: 1. What topics or categories are these prompts in? 2. What does a prospect appear to be searching for when [brand name] doesn't appear? 3. Group these into 3–5 thematic clusters — these represent distinct content gap areas 4. For each cluster, identify what type of content [brand name] would need to appear for these queries ``` The most-observed queries where \[brand name] isn't showing up — ranked by urgency. ```text theme={null} For [brand name], pull prompt variants where brand_present = false. Sort by observation_count descending. Return the top 25. For each: - Show the prompt text - Show the platform - Show the observation count - Note whether it's a branded or unbranded query Flag any branded queries in this list — a brand missing its own branded queries at high observation volume is an urgent issue. ``` Category queries where \[brand name] is close to appearing — the fastest visibility gains available right now. ```text theme={null} For [brand name], I want to identify prompts where [brand name] is close to appearing but isn't yet. Pull prompt variants where: - brand_present = false - branded = false - The prompt text contains keywords related to [brand name]'s core category (use search filter: "[category keyword]") List up to 30 results. For each, explain why [brand name] likely doesn't appear and what content change would most likely flip this to a brand_present = true result. ``` *** Full workflow: gap analysis → prioritized Notion tracker with content recommendations. Check whether competitors are winning the gaps you just found. # Brand Presence & Visibility Source: https://developers.scrunch.com/mcp/prompts/visibility-overview Starter MCP prompts that calculate your AI visibility score and establish where your brand stands across tracked prompts, platforms, and reporting cycles. Start here. These four prompts give you a complete picture of \[brand name]'s visibility across all tracked prompts and platforms before you dig into gaps or competitive analysis. Replace `[brand name]` with the brand you're analyzing and paste directly into Claude with Scrunch connected. *** Overall visibility rate across all tracked prompts and platforms, ranked by AI model. ```text theme={null} For [brand name] in Scrunch, calculate the brand's overall AI visibility rate. 1. Pull the total number of prompt variants tracked for [brand name] — count only 2. Pull the count of variants where brand_present = true — count only 3. Calculate the visibility rate: (brand present / total) × 100 4. Break this down by platform — run the same brand_present=true count filtered to each LLM (ChatGPT, Perplexity, Claude, Gemini, Grok, Meta) 5. Rank platforms from highest to lowest visibility rate Present the overall rate, the platform breakdown, and flag any platform where [brand name] is significantly above or below its average. ``` Which queries and topics is \[brand name] already appearing in? What patterns explain those wins? ```text theme={null} For [brand name], pull prompt variants filtered to brand_present = true. Limit to 50 results. For this set, tell me: 1. Which platforms have the most brand presence 2. Which tags or topic categories appear most frequently — what topics does [brand name] win on? 3. Are these primarily branded queries (someone asking directly about [brand name]) or unbranded category queries? 4. What does the brand appear to be doing well based on the types of prompts where it appears? ``` Is \[brand name] showing up every time someone asks an AI about it directly? It should be — flag if not. ```text theme={null} For [brand name], pull prompt variants filtered to: - branded = true (queries specifically asking about [brand name]) - brand_present = false Count how many branded queries exist where [brand name] is NOT appearing in AI responses. This should be zero or near-zero for a healthy brand — flag if it's significant. List up to 20 of these prompts so I can see which branded queries the brand is missing. ``` Side-by-side visibility rates for every platform — which are strong, which are priority gaps? ```text theme={null} For [brand name], run the following and report counts for each: 1. Total prompt variants (no filter) 2. brand_present = true, platform = chatgpt 3. brand_present = true, platform = perplexity 4. brand_present = true, platform = claude 5. brand_present = true, platform = gemini 6. brand_present = true, platform = grok 7. brand_present = true, platform = meta For each platform, calculate the visibility rate vs. total variants on that platform. Rank platforms. Flag any where visibility is under 20% — those are priority gaps. ``` Don't just trust the aggregate rate — read how the brand is actually being described. ```text theme={null} For [brand name], pull the actual response text behind the numbers instead of just the aggregate rate. 1. Pull prompt variants filtered to brand_present = true. Take the 5 highest-observation results. 2. For each, fetch the full response with get_response — the raw text, not just the presence flag. 3. Read how [brand name] is actually described: is it a recommendation, a passing mention, or one option among many? Summarize: does the way [brand name] is described match how the brand wants to be positioned, or is the framing off even when presence is technically counted as a win? ``` *** Find where the brand is absent and which gaps are most urgent to address. Use these numbers in an automated weekly brief saved to Notion and posted to Slack. # Visualize It Source: https://developers.scrunch.com/mcp/prompts/visualize-it MCP prompts that turn a metric question directly into a Scrunch Explorer chart or saved dashboard, using generate_explorer_chart and create_explorer_dashboard. Sometimes a number needs a picture. These prompts use Scrunch's Explorer tools to turn any metric question into an interactive chart or a saved multi-tile dashboard, each returning a link you can revisit or share. *** Turn a plain-English question directly into a chart instead of a table of numbers. ```text theme={null} For [brand name], chart [metric — e.g. presence, position, sentiment, or citations] over the last [30/90] days, broken down by [platform / competitor / tag — whichever applies]. Give me the link to the chart, and tell me in one sentence what it shows. ``` Assemble several metrics into one saved view instead of asking for them one at a time. ```text theme={null} For [brand name], build an Explorer dashboard with tiles for: overall presence rate, sentiment breakdown, citation ownership split, and share of voice vs. our top 3 competitors. Mix a couple of headline "card" tiles with line or bar charts for the trend-based ones. Give me the dashboard link when it's ready. ``` Compare directly instead of eyeballing two separate numbers. ```text theme={null} For [brand name], chart presence rate over the last 90 days with [competitor name] overlaid on the same chart for direct comparison. Tell me the link, and call out any point in the period where the two lines crossed or diverged sharply. ``` *** The full workflow version of the dashboard-building prompt above, with a structured tile proposal step. For a ranked table instead of a chart, when you need to triage rather than visualize. # White Space & Growth Opportunities Source: https://developers.scrunch.com/mcp/prompts/white-space MCP prompts that surface uncontested AI search territory — queries where neither you nor competitors appear yet, ranked by first-mover value. White space in AI search is where no brand has established authority yet. These prompts identify that territory, track how emerging topics are developing, and surface the audience segments with the lowest AI coverage. *** Queries where AI has no clear brand to reference — \[brand name]'s first-mover opportunity. ```text theme={null} For [brand name], I want to find prompts where neither [brand name] nor its top competitors appear in AI responses. Pull variants where: - brand_present = false - branded = false Then cross-reference by pulling variants from this set where competitor_present is also false for the top 3 competitors. These are uncontested queries — topics where AI has no clear brand to reference. Group by tag and identify the 3 most commercially relevant white space clusters where [brand name] could be first to establish a presence. ``` Recently added prompts — is \[brand name] keeping pace with how its category is evolving in AI search? ```text theme={null} For [brand name], pull variants sorted by created_at descending — the most recently added prompts. Limit to 50. For this set: 1. What new topics or question types are being tracked? 2. Which of these new prompts have brand_present = true vs. false? 3. Are there new topic areas where [brand name] is not yet appearing? This shows whether [brand name]'s visibility is keeping pace with how its category is evolving in AI search. ``` Which buyer personas are asking questions that \[brand name] isn't answering anywhere in AI responses? ```text theme={null} For [brand name], pull prompt variants and identify which ones have a persona assigned. For persona-filtered prompts where brand_present = false, tell me: 1. Which personas are asking questions that [brand name] isn't answering in AI? 2. Which personas have the highest gap rate? 3. What types of questions is each persona asking that [brand name] should be addressing? These gaps represent audience segments where [brand name] has no AI visibility. ``` *** Once you've found the white space, use configuration prompts to add and tag new prompts. Setting up a new brand? Seed an initial prompt library covering white space from day one. # Connect Claude, ChatGPT, or Cursor to Scrunch MCP Source: https://developers.scrunch.com/mcp/setup Step-by-step setup to connect the Scrunch MCP server to Claude, ChatGPT, Microsoft Copilot Studio, Cursor, VS Code, or Windsurf using OAuth in 5 minutes. All setup flows connect to the same server and use the same OAuth sign-in — your Scrunch account credentials, no API key required. Pick your AI client below. **MCP server URL:** `https://app.scrunchai.com/api/mcp` All platforms below use this URL. Authentication happens via Scrunch's standard OAuth sign-in flow; no API key or shared secret is needed. Custom connectors work across Free, Pro, Max, Team, and Enterprise Claude plans. How you add Scrunch depends on whether you're on a personal plan or part of a Team or Enterprise organization. Free plans are limited to one active custom connector at a time. In the Claude web app ([claude.ai](http://claude.ai)) or Claude desktop app, click **Customize** in the sidebar navigation. Claude Customize setting In the Settings sidebar, select **Connectors**. You'll see built-in connectors (Google Drive, Slack, Notion, etc.) followed by any custom connectors you've already added. Claude connectors setting Click the **+** button and select **Add custom connector**. In the dialog that opens, enter: * **Name:** `Scrunch AI` (or whatever you'd like to call it) * **Remote MCP server URL:** `https://app.scrunchai.com/api/mcp` * **OAuth Client ID / Client Secret:** Leave blank. These are only needed if you're hosting your own OAuth provider. claude-custom-connector Claude redirects you to Scrunch to authenticate. Sign in with your Scrunch account, approve the connection, and Claude returns to the Connectors page with the connector active. On Team and Enterprise plans, only **owners** can add custom connectors. Once added, the connector becomes available for all members in your organization to enable. In the Claude web app ([claude.ai](http://claude.ai)) or Claude desktop app, click **Customize** in the sidebar navigation. In the Settings sidebar, select **Connectors**. Click the **+** button and select **Add custom connector**. In the dialog that opens, enter: * **Name:** `Scrunch AI` * **Remote MCP server URL:** `https://app.scrunchai.com/api/mcp` * **OAuth Client ID / Client Secret:** Leave blank. claude-custom-connector Claude redirects you to Scrunch to authenticate. Sign in with your Scrunch account and approve the connection. The Scrunch connector is now available for members in your organization. Regular members on Team and Enterprise plans cannot add custom connectors — that's restricted to org owners. Once an owner has added Scrunch, you can enable it for your own account. Have an org owner follow the **Team & Enterprise — Owners** tab to add the Scrunch connector. They only need to do this once for the whole organization. Once the connector has been added, go to **Customize → Connectors** in your Claude account. Scrunch AI will appear in the list. Toggle the connector on. Claude redirects you to Scrunch to sign in with your own Scrunch account. Your individual brand access and permissions are determined by your Scrunch account — not the owner's. **Enabling the connector in a chat** — When you start a new conversation, click the connector icon in the message composer and toggle **Scrunch AI** on for that chat. To enable it by default for all new chats, go to **Settings → Connectors → Configure** on the Scrunch AI connector. Claude Code is the Claude CLI tool. Run the following command in your terminal: ```bash theme={null} claude mcp add scrunch --transport streamable-http https://app.scrunchai.com/api/mcp ``` Claude Code will prompt you to authenticate with your Scrunch account the first time you use a Scrunch tool in a session. **Verify the connection:** ```text theme={null} List my Scrunch brands ``` Your assistant should respond with the brands accessible in your Scrunch org. Requires a paid ChatGPT plan (Plus, Pro, Team, Enterprise, or Edu). Plus and Pro accounts get read-only access; Team, Enterprise, and Edu accounts get full read + write access. **Critical:** You must remove `openid` from the OAuth scopes in **two separate places** during setup (steps 5 and 6 below). If you miss either one, authentication will fail. Click your profile picture in ChatGPT and choose **Settings**. Open the **Apps** tab, then click **Advanced Settings** at the bottom. Screenshot 2026 05 14 At 8 58 59 AM In Advanced Settings, toggle **Developer Mode** on. Workspace owners can also enable this org-wide under **Workspace Settings → Permissions & Roles → Connected Data → Developer mode**. Screenshot 2026 05 14 At 8 59 23 AM Navigate back to the main **Apps** tab. With Developer Mode enabled, a **Create app** widget appears. Screenshot 2026 05 14 At 8 56 25 AM Click **Create app** and fill in: * **Name / icon / description:** Anything you like — `Scrunch AI` works well. * **MCP Server URL:** `https://app.scrunchai.com/api/mcp` * **Authentication:** OAuth Inside the Create app form, expand **Advanced settings**. In the **Scopes** field, deselect or delete `openid`. Leave all other default scopes. Still in Advanced settings, scroll to the bottom. Find the **OIDC scope supported** field and delete `openid` from that field as well. Both removals are required. Check the trust acknowledgment and click **Create**. ChatGPT redirects you to Scrunch to authenticate. Sign in and approve the connection. In any new chat, click the **apps / +** menu in the composer, choose **Developer mode**, and select **Scrunch AI**. **Plan limits** — Plus and Pro accounts have read-only access. Features like `list_brands` and `get_presence_metrics` work on any plan, but operations that modify data — `create_brand`, `archive_prompt`, `update_tags` — require a Team, Business, Enterprise, or Edu workspace. Microsoft Copilot Studio lets you attach the Scrunch MCP to any custom agent. You'll need an agent already created before connecting Scrunch to it. In Microsoft Copilot Studio, open the agent you want to extend with Scrunch. From the agent's left navigation, choose **Tools**. Click **+ Add a tool**. In the dialog, choose **New tool**, then select **Model Context Protocol**. This launches the MCP onboarding wizard. Provide: * **Server name:** `Scrunch AI` * **Server description:** `AI brand monitoring and analytics` * **Server URL:** `https://app.scrunchai.com/api/mcp` Click **Create**. Copilot Studio redirects you to Scrunch to authenticate. Sign in with your Scrunch account and approve the connection. After connecting, you'll see the full list of Scrunch features. Select which ones the agent should have access to, click **Add to agent**, then save and publish your agent. **Editing the connector later** — If you need to update the connector details (e.g., swap to a different Scrunch account), open **Power Apps → Custom connectors**, find the Scrunch entry, and update there. The change propagates back into Copilot Studio automatically. Grok (grok.com / xAI) supports custom MCP connectors on all paid plans. Free users may have limited or no access to custom connectors. Log in to [grok.com](https://grok.com) and navigate to **Connectors** (direct link: [grok.com/connectors](https://grok.com/connectors) or via the main menu). Grok connectors Click **New Connector** (or the equivalent + button), then select **Custom**. Grok new connector Enter: * **Name:** `Scrunch AI` (or your preferred name) * **MCP Server URL:** `https://app.scrunchai.com/api/mcp` Leave any OAuth Client ID / Secret fields blank unless instructed otherwise (Scrunch handles authentication via its standard OAuth flow). Grok custom connector Click **Add** / **Create**. Grok will redirect you to Scrunch to sign in with your Scrunch account and approve the connection. Once approved, the connector becomes active. **Enabling in a chat** — In a new conversation, look for the connector / tools icon or sidebar. Toggle **Scrunch AI** on for that chat. You can set it as default for new chats in the connector settings. **MCP server URL:** `https://app.scrunchai.com/api/mcp`\ Authentication uses Scrunch's standard OAuth sign-in. No API key is required. Go to **Cursor Settings → Tools & Integrations → MCP**. Click **Add custom server** and enter: * **Name:** `scrunch` * **Server URL:** `https://app.scrunchai.com/api/mcp` * **Transport type:** Streamable HTTP Save the configuration. On first use, Cursor will prompt you to authenticate with your Scrunch account. **Verify the connection:** ```text theme={null} List my Scrunch brands ``` Create a `.vscode/mcp.json` file in your workspace root with the following content: ```json theme={null} { "servers": { "scrunch": { "type": "http", "url": "https://app.scrunchai.com/api/mcp" } } } ``` Save the file. VS Code (with GitHub Copilot) will detect the MCP configuration and prompt you to authenticate with Scrunch on first use. To share the configuration across your team, commit `.vscode/mcp.json` to your repository. Go to **Windsurf Settings → MCP**. Click **Add server** and enter: * **Name:** `scrunch` * **Server URL:** `https://app.scrunchai.com/api/mcp` * **Transport type:** Streamable HTTP Save and restart Windsurf if prompted. On first use, Windsurf will redirect you to authenticate with your Scrunch account. **Verify the connection:** ```text theme={null} List my Scrunch brands ``` *** ## Troubleshooting | Symptom | Likely cause | Fix | | ------------------------------------------ | -------------------------------------------- | ----------------------------------------------------------------------------- | | Authentication fails immediately | Signed in with the wrong account | Sign out of Scrunch in your browser, then reconnect using the correct account | | "No brands found" | Your Scrunch account has no brand access | Ask your org admin to grant you access to at least one brand | | ChatGPT auth fails | `openid` not removed from both scope fields | Recreate the app and follow steps 5–6 carefully | | Tools not appearing in Claude | Connector not enabled for this chat | Click the connector icon in the composer and toggle Scrunch AI on | | Free Claude plan limit | Free plan is limited to one custom connector | Remove an existing custom connector or upgrade your plan | | Scrunch connector not visible (org member) | Owner hasn't added it to the org yet | Ask an org owner to follow the Team & Enterprise — Owners setup steps | Need more help? Contact your Scrunch CSM or email [support@scrunchai.com](mailto:support@scrunchai.com). *** ## Next steps Browse all MCP features with descriptions and example prompts for each. Step-by-step workflows for reporting, competitive analysis, prompt management, and more. # Scrunch MCP Feature Reference and Example Prompts Source: https://developers.scrunch.com/mcp/tools Reference for 33 Scrunch MCP tools covering reporting, responses, prompts, brand configuration, agent traffic, and help docs, with example prompts. Scrunch's MCP connection gives your AI assistant access to 33 features. These are called automatically in response to natural-language prompts — you never need to reference them by name. Related categories are grouped into the tabs below; use them to jump to what you need. Each description and example prompt shows what a feature does and how to ask for it. Everything for measuring and visualizing AI visibility — the core metrics, plus the Explorer charts and dashboards built on top of them. ## Metrics The four core analytics features. Each accepts the same set of filters: AI platform, country, persona, funnel stage, tags, topics, branded vs. non-branded prompts, and a date range. Returns brand mention rate (presence) over time — the percentage of AI responses where your brand is mentioned. Set `include_competitors=true` to compare brands side by side. **Example prompts** * "How has our presence in ChatGPT trended over the last 90 days?" * "Compare our mention rate vs. all tracked competitors over the past month." * "Show me weekly presence for our brand on Perplexity since January." Returns how often the brand appears in the top, middle, or bottom position within AI responses — relative to other brands mentioned in the same response. **Example prompts** * "Are we showing up first or last when AI assistants list options in our category?" * "What's our average position on ChatGPT for consideration-stage prompts?" Returns sentiment breakdown (positive, mixed, negative) for brand mentions in AI responses. **Example prompts** * "What's the sentiment trend for our brand on Perplexity in the last 30 days?" * "Is sentiment improving or declining compared to last quarter?" * "Compare our sentiment vs. our top competitor across all platforms." Returns how AI-cited URLs break down by ownership: brand-owned, competitor-owned, and third-party. Use `citation_owner` to focus on one type, or `brand_mentioned` to filter by branded vs. non-branded prompts. **Example prompts** * "What share of citations come from third-party sites for our non-branded queries?" * "Which competitor's domains are getting cited the most in our category?" * "How has our owned citation share changed over the last 60 days?" ## Explorer Turn a metric question into an interactive Scrunch Explorer chart or a saved dashboard. Both return a deep link that opens the Explorer pre-configured — great for exploring the data behind an answer or saving a view you'll revisit. Builds an Explorer chart from a metric/breakdown/filter spec and returns a deep link that opens the Explorer with that chart already configured. Your assistant offers this after answering an analysis question so you can explore the chart behind the numbers. Supports line, bar, and pivot visualizations, breakdowns (e.g. by platform or competitor), custom date ranges, and comparison overlays. **Example prompts** * "Chart our mention rate by AI platform over the last 30 days." * "Visualize our share of voice vs. our top 3 competitors, weekly." * "Show citations broken down by owner as a bar chart, and give me the link." Creates a saved dashboard of metric tiles for a brand and returns a deep link to it. Each tile uses the same spec as `generate_explorer_chart` plus a title — mix a few headline "card" tiles with line/bar charts for trends and breakdowns. **Example prompts** * "Build a dashboard for Acme Coffee with presence, sentiment, and citation trends." * "Create a competitive dashboard comparing our share of voice against Blue Bottle and Stumptown." Pull the raw AI responses Scrunch has captured — full response text, citations, and per-competitor evaluations for individual answers. Use this when you need to read what an AI actually said, not just an aggregate metric. Lists individual AI responses (observations) for a brand. Filter by platform, prompt, persona, funnel stage, date range, and whether the response includes shopping results. Results are paginated with `limit` (default 10, max 100) and `offset`. By default it returns observation IDs only, to keep payloads small. Ask for full detail (`ids_only=false`) to include response text, evaluation data, citations, and competitor analysis for every listed response — or fetch IDs first and pull individual responses with `get_response`. Use this when you want to audit a specific answer, compare what two platforms said about the same prompt, or pull a sample of recent responses for qualitative review. For aggregated trends, use the metrics features instead. **Example prompts** * "Show me the 10 most recent ChatGPT responses for Acme Coffee where our brand wasn't mentioned." * "Pull every Perplexity response from last week for prompt #482 so I can compare them side by side." * "Find responses on Google AI Overviews in the comparison stage that include shopping results." * "Give me the raw responses Claude returned for the 'sustainability' persona in April." Fetches a single AI response by ID with full evaluation data, citations, and competitor analysis. Use it to inspect a response ID returned by `list_responses`. **Example prompts** * "Pull the full text and citations for response #918273." * "What did the AI actually say in that response — and which URLs did it cite?" Manage the seed prompts Scrunch runs against AI platforms on your behalf, and the tags you use to organize them. ## Prompts Browse and manage the seed prompts Scrunch runs against AI platforms on your behalf. Lists the prompt variants Scrunch is monitoring for a brand. Filterable by tag, persona, country, branded vs. non-branded, citation domain, funnel stage, and more. **Example prompts** * "Show me the top 20 non-branded prompts for Acme Coffee in the US." * "List all the prompts tagged 'consideration' for our brand." * "Browse the prompts in the awareness stage — I want to see what's covered before I add new ones." Adds a new seed prompt for a brand, optionally with category, key topics, persona, platforms, and tags. **Example prompts** * "Add a prompt to Acme Coffee: 'What's the best mail-order coffee subscription for offices?' Tag it as 'consideration'." * "Create 5 new awareness-stage prompts for Acme Coffee focused on sustainability." Archives (soft-deletes) a seed prompt so it stops running. History is preserved. **Example prompts** * "Archive prompt #482 — we don't need to track that one anymore." * "Archive all prompts tagged 'Q1 campaign' for Acme Coffee." Restores previously archived prompts so they resume running. **Example prompts** * "Restore the prompts I archived last month for Acme Coffee." * "Unarchive all prompts in the 'seasonal' tag so they start running again." ## Tags Read, add, and remove the tags attached to prompts so you can slice metrics by funnel stage, persona, campaign, or any custom dimension. Returns all tags currently configured for a brand. **Example prompts** * "What tags do we use for Acme Coffee?" * "Show me the full tag list across all our brands." Adds a single tag to a list of prompts (up to 500 at a time). Existing tags are preserved — this only appends, never replaces. The tag is created for the brand if it doesn't already exist, and prompts that already have it are skipped. **Example prompts** * "Tag prompts #482 and #483 with 'mobile'." * "Add the 'evergreen' tag to every prompt in the awareness stage." Removes a single tag from a list of prompts. Prompts that don't have the tag are ignored, and other tags on each prompt are unaffected. **Example prompts** * "Remove the 'Q1 campaign' tag from prompts #482 and #483." * "Untag 'draft' from all the prompts I created yesterday." Set up and maintain what Scrunch tracks for each brand — the brands themselves, their competitors, and the personas you slice metrics by. ## Brands Look up and manage the brands tracked in your Scrunch organization. Lists all brands accessible within the authenticated organization, including name, website, status, and configuration details. **Example prompts** * "Show me all the brands I have access to in Scrunch." * "Which brands in our org have the most prompts configured?" Creates a new brand within the organization. Name, website, and status are required. **Example prompts** * "Create a new Scrunch brand for Acme Coffee, website acmecoffee.com." * "Set up a new brand for our UK subsidiary — name is Acme Coffee UK, website acmecoffee.co.uk." Updates an existing brand's name, alternative names, websites, geo, or case-sensitivity settings. **Example prompts** * "Add 'Acme Coffee Co.' as an alternative name for the Acme Coffee brand." * "Switch the geo for our Acme brand from US to UK." ## Competitors Manage the competitors tracked alongside each brand. Lists all competitors being tracked for a specific brand, including their alternative names and websites. **Example prompts** * "Who are we tracking as competitors for Acme Coffee?" * "List the competitors for all our brands." Adds a new competitor to a brand, with an optional list of alternative names and websites. **Example prompts** * "Add Blue Bottle as a competitor for Acme Coffee with website bluebottlecoffee.com." * "Start tracking Stumptown Coffee as a competitor — add their main site and their DTC site." Updates an existing competitor's name, alternative names, or websites. **Example prompts** * "Add bluebottle.com as an alternative website for the Blue Bottle competitor." * "Rename the competitor 'Blue Bottle' to 'Blue Bottle Coffee' for Acme Coffee." Soft-deletes a competitor from a brand's tracked list. History is preserved; the competitor just stops appearing in new data. **Example prompts** * "Stop tracking Blue Bottle as a competitor for Acme Coffee." * "Remove the three competitors we added last year that are no longer relevant." ## Personas Manage the personas tracked alongside each brand. Personas represent distinct customer segments (for example, "first-time buyers" or "enterprise IT admins") and can be attached to prompts so you can slice metrics by audience. Lists all personas configured for a brand, including their names and descriptions. **Example prompts** * "What personas do we have for Acme Coffee?" * "List the personas across all our brands." Creates a new persona on a brand. Requires a name and description. **Example prompts** * "Create a persona called 'Office manager' for Acme Coffee — someone responsible for stocking the office kitchen." * "Add a 'Home barista' persona for Acme Coffee focused on enthusiasts who grind their own beans." Soft-deletes a persona from a brand. Historical data is preserved; the persona just stops appearing in new prompts and filters. **Example prompts** * "Archive the 'Q1 test' persona on Acme Coffee." * "Remove the personas we added during the pilot — they're no longer used." Assigns, changes, or removes the persona on a batch of prompts in one call. Pass a persona ID to attach it, or omit the persona to clear it. **Example prompts** * "Assign the 'Office manager' persona to all prompts tagged 'workplace' for Acme Coffee." * "Clear the persona on prompts #482, #491, and #503 — they should be persona-agnostic." Bring AI bot crawl logs into Scrunch, or pull them out for analysis elsewhere. Useful for understanding how often GPTBot, ClaudeBot, PerplexityBot, and others are crawling your site. Ingests agent traffic logs from a CSV. Required columns: `domain`, `user_agent`, `url`, `path`, `method`, `status_code`, `timestamp`. Bot classification happens automatically on import. **Example prompts** * "Import this week's bot traffic CSV for acmecoffee.com." * "Load the server logs I just exported — here's the CSV." Exports agent traffic data as a CSV. Filterable by date range, site, path, and aggregation level (day or week). **Example prompts** * "Export the last 30 days of GPTBot traffic to acmecoffee.com." * "Give me a weekly summary of all AI bot activity on our site in Q1." Answer questions about how Scrunch works. Your assistant reaches for the Help Center first, then falls back to Scrunch's public web content — always citing its sources. Lists every Scrunch Help Center collection and the articles inside each one. Your assistant uses this to find the article that best matches a support-style question (features, troubleshooting, onboarding, plan/billing UX), then reads it with `get_scrunch_help_article`. **Example prompts** * "How do I set up a new brand in Scrunch?" * "What's the difference between branded and non-branded prompts?" Fetches the full body of a single Help Center article by ID — discovered via `list_scrunch_help_collections`. The assistant quotes or summarizes the article and cites its URL under a `Sources:` section. **Example prompts** * "Walk me through configuring competitors, and cite the help docs." * "Explain how funnel stages work, with a link to the article." Fetches a Scrunch-owned web page and returns its main content as markdown. Used when the Help Center doesn't cover a question and the answer lives in Scrunch's public content — product and feature pages on `scrunchai.com`, or REST/SDK reference on `developers.scrunch.com`. Only `scrunch.com`, `scrunchai.com`, and `developers.scrunch.com` (and their subdomains) are allowed. **Example prompts** * "Summarize the Agent Experience Platform product page." * "What do the developer docs say about API authentication?" Lightweight helpers your assistant uses automatically behind the scenes. Returns the signed-in user's email, basic profile, and accessible brands. Your assistant calls this to determine which brands you have access to without asking you to look up a brand ID. **Example prompts** * "What brands do I have access to in Scrunch?" * "Which org am I connected to right now?" Returns the server's current date in UTC. Your assistant uses this to anchor relative date phrases like "the last 30 days" or "this quarter" before constructing analytics queries. You don't need to call this directly. # Agent Traffic to a Spreadsheet Dashboard Source: https://developers.scrunch.com/mcp/workflows/agent-traffic-to-spreadsheet Export Scrunch's AI bot crawl data as CSV and turn it into a pivoted, chartable spreadsheet showing GPTBot, ClaudeBot, and PerplexityBot activity over time. `export_agent_traffic` gives you a CSV of raw crawl events — every hit from GPTBot, ClaudeBot, PerplexityBot, and other AI crawlers, with a timestamp, path, and status code. That's exactly what you want for a dashboard and exactly what you don't want to read row by row. This workflow has Claude do the export and the pivoting in one pass, so you land on a chart, not a CSV. **Tools used in this workflow** | Tool | Required? | Used for | | ------------------------------ | --------------------- | ---------------------------------------- | | Scrunch MCP | Required | Exporting the agent traffic CSV | | Google Sheets MCP or Excel MCP | Required (choose one) | Building the pivoted, chartable workbook | *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [site domain] in Scrunch, export the last [30/60/90] days of agent traffic and turn it into a Google Sheets dashboard. Step 1 — Export the data: Export agent traffic for [site domain] from [start date] to [end date], aggregated by day. Step 2 — Build the raw data tab: Create a new Google Sheet called "[site domain] Agent Traffic — [month/year]". Add a "Raw Export" tab and load the exported rows: date, bot name, path, hit count. Step 3 — Build the pivot: On a new "By Bot" tab, pivot the raw data into: one row per date, one column per bot (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, and any others present), with hit count as the value. Add a Total column. Step 4 — Chart it: Create a stacked area chart on a "Chart" tab plotting hit count over date, broken out by bot, using the "By Bot" tab as the source. Step 5 — Summarize: Which bot crawls [site domain] most? Is total crawl volume trending up or down over the period? Are there any days with an unusual spike or drop worth flagging? ``` **What you get:** A three-tab spreadsheet — raw export, a per-bot pivot, and a stacked area chart — that turns a flat CSV into something you can actually read crawl trends off of at a glance. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [site domain] in Scrunch, export the last [30/60/90] days of agent traffic and turn it into an Excel dashboard. Step 1 — Export the data: Export agent traffic for [site domain] from [start date] to [end date], aggregated by day. Step 2 — Build the raw data sheet: Create a new workbook called "[site domain] Agent Traffic — [month/year]". Add a "Raw Export" worksheet and load the exported rows: date, bot name, path, hit count. Step 3 — Build the pivot: On a new "By Bot" worksheet, pivot the raw data into: one row per date, one column per bot (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, and any others present), with hit count as the value. Add a Total column. Step 4 — Chart it: Create a stacked area chart on its own worksheet plotting hit count over date, broken out by bot, using the "By Bot" sheet as the source. Step 5 — Summarize: Which bot crawls [site domain] most? Is total crawl volume trending up or down over the period? Are there any days with an unusual spike or drop worth flagging? ``` **What you get:** A three-sheet workbook — raw export, a per-bot pivot, and a stacked area chart — that turns a flat CSV into something you can actually read crawl trends off of at a glance. *** ## Tips If a bot's crawl volume to a specific path jumped recently, check that page's citation rate in Scrunch for the same window — a crawl spike followed by a citation increase is a strong signal that the crawl directly fed a retrieval or indexing update. Add "filtered to paths starting with \[/blog/ or /docs/]" to Step 1 if you only care about crawl activity on a specific site section rather than the whole domain. If a bot you expect to see (e.g. PerplexityBot) shows zero or near-zero hits across the whole period, that's worth investigating on its own — check robots.txt isn't blocking it and that the relevant pages are reachable without JavaScript rendering. Keep the same workbook and ask Claude to append the new month's export as additional rows on "Raw Export" rather than creating a new file each time — the pivot and chart will pick up the extended range automatically if they're built off the full sheet rather than a fixed row range. *** Pair crawl activity with Google Analytics to see whether crawl attention is turning into referral traffic. Go one step further and check whether the pages getting crawled are the same ones driving citations and conversions. # Measure AI Visibility's Impact on Traffic Source: https://developers.scrunch.com/mcp/workflows/ai-visibility-traffic-impact Pair Google Analytics with Scrunch after lifting AI presence on a topic to confirm whether traffic followed and build the ROI case for AI visibility work. Improving your AI visibility is the work. Proving it drove results is what gets the next round of budget. This workflow connects Scrunch presence improvements to Google Analytics traffic data, so you can show exactly which pages got more traffic after they started getting cited by AI engines. **Tools used in this workflow** | Tool | Required? | Used for | | -------------------- | ----------- | --------------------------------------------------------- | | Scrunch MCP | Required | AI visibility metrics before and after content changes | | Google Analytics MCP | Recommended | Traffic data to correlate with AI visibility improvements | No Google Analytics MCP? Use the **Scrunch only** tab to pull the visibility side of the story — then compare to GA manually. *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name], measure whether our AI visibility improvements have driven traffic growth. Step 1 — Pull before/after AI visibility from Scrunch: Get presence metrics for [brand name] for two periods: - Before period: [start date] to [end date] - After period: [start date] to [end date] For each period, show: overall presence rate, presence rate per tag, and citation rate to [brand domain] per tag. Identify the tags where presence improved the most — these are the topics we'll cross-reference against traffic. Step 2 — Pull corresponding traffic data from Google Analytics: For the same two date ranges, get: - Organic traffic to [specific pages we optimized or created] — sessions and users, before vs. after - Overall organic traffic to [domain] — any meaningful change in the period? - Direct traffic — did brand awareness lift alongside AI visibility? - Referral traffic from AI sources (Perplexity, ChatGPT, etc.) — are AI engines showing up as referrers yet? Step 3 — Find the correlation: For each page or topic where Scrunch shows improved AI presence: - Did organic traffic to that page increase in the same window? - What's the % change in traffic vs. the % change in AI presence rate? - Are there topics where AI visibility improved but traffic hasn't followed yet? (May just need more time) - Any traffic gains that don't correlate with AI visibility changes? (Worth flagging) Step 4 — Write the impact summary: Summarize the connection between AI visibility improvements and traffic outcomes. Be specific: which pages moved, by how much, over what timeframe. Flag anything that looks like a lagging indicator (visibility up, traffic not yet) and anything that looks like an outlier. ``` **What you get:** A clear before/after story connecting AI visibility work to traffic outcomes — specific enough to present to a client or leadership team as evidence that Scrunch-driven content improvements are working. No GA connected? This pulls the visibility side of the story. You can compare it against your GA data manually. ```text theme={null} For [brand name] in Scrunch, give me a before/after comparison of AI visibility for topics where we've published or optimized content. Compare these two periods: - Before: [start date] to [end date] - After: [start date] to [end date] For each period, show: 1. Overall presence rate and the change 2. Presence rate per tag — which topics improved the most? 3. Citation rate to [brand domain] per tag — are more citations pointing to our pages? 4. For the tags that improved most: which specific prompts are now showing brand_present = true that weren't before? Summarize: what moved, by how much, and which pages are now being cited that weren't previously. I'll cross-reference this against Google Analytics traffic data manually. ``` *** ## Tips AI citation improvements typically take 30–90 days to show up in traffic data, depending on how frequently AI engines refresh their training or retrieval indexes. Run this workflow at the 30-day mark to check for early signals, then again at 60 and 90 days for a clearer picture. Don't write off a page because it hasn't moved in the first month. You're looking for directional evidence, not statistical proof. If a page's AI presence went from 10% to 45% and organic traffic grew 30% in the same period, that's a meaningful signal — even if you can't isolate AI as the sole cause. Be honest about confounding factors (seasonality, other content changes) when presenting the data. Some AI engines pass referral data — Perplexity in particular shows up in GA referral reports. ChatGPT Browse traffic sometimes appears as well. Look for these as direct signals in your referral report. Low numbers are normal — this channel is still early. The trend matters more than the absolute volume. Run this workflow monthly and save the output to Notion or Google Docs using the Monthly Client Report workflow. After 3–4 months you'll have a longitudinal dataset showing how AI visibility changes and traffic outcomes move together over time — much more compelling than a single before/after snapshot. *** Start here before creating content — combine SEO keyword data with Scrunch gaps to prioritize what to build. Roll this measurement into a full monthly report with competitive context and recommendations. # Bulk Prompt Import from a Spreadsheet Source: https://developers.scrunch.com/mcp/workflows/bulk-prompt-import-from-sheets Read a spreadsheet of seed queries, tags, and personas you already have and bulk-create them as tracked Scrunch prompts in one conversation. Most teams don't start from zero — there's already a spreadsheet somewhere with a curated list of queries a client cares about, or one inherited from a previous tool. This workflow reads that spreadsheet directly and creates every row as a tracked Scrunch prompt, instead of re-typing the list one by one. **Tools used in this workflow** | Tool | Required? | Used for | | ------------------------------ | --------------------- | ----------------------------------------- | | Google Sheets MCP or Excel MCP | Required (choose one) | Reading the source list of queries | | Scrunch MCP | Required | Bulk-creating prompts, tags, and personas | *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, bulk-import the prompt list from [spreadsheet name or URL]. Step 1 — Read the source list: Open [spreadsheet name or URL] and read the [sheet/tab name] tab. Expect columns for: query text, tag (optional), persona (optional), platform (optional). Show me the first 10 rows so I can confirm the column mapping is right before continuing. Step 2 — Check for duplicates: List existing prompt variants for [brand name]. Flag any rows from Step 1 that closely match a prompt that's already tracked, so we don't create duplicates. Step 3 — Create the new prompts: For every non-duplicate row, create a Scrunch prompt using the query text. If a tag column has a value, apply that tag (creating it first if it doesn't exist). If a persona column has a value and that persona exists on this brand, assign it. Step 4 — Confirm: Summarize: how many prompts were created, how many were skipped as duplicates, and how many tags were newly created versus reused. ``` **What you get:** Every row in the spreadsheet turned into a tracked Scrunch prompt with its tags and persona already applied — a full prompt library migrated from a spreadsheet in one pass instead of hundreds of individual clicks. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, bulk-import the prompt list from [workbook name or path]. Step 1 — Read the source list: Open [workbook name or path] and read the [worksheet name] sheet. Expect columns for: query text, tag (optional), persona (optional), platform (optional). Show me the first 10 rows so I can confirm the column mapping is right before continuing. Step 2 — Check for duplicates: List existing prompt variants for [brand name]. Flag any rows from Step 1 that closely match a prompt that's already tracked, so we don't create duplicates. Step 3 — Create the new prompts: For every non-duplicate row, create a Scrunch prompt using the query text. If a tag column has a value, apply that tag (creating it first if it doesn't exist). If a persona column has a value and that persona exists on this brand, assign it. Step 4 — Confirm: Summarize: how many prompts were created, how many were skipped as duplicates, and how many tags were newly created versus reused. ``` **What you get:** Every row in the workbook turned into a tracked Scrunch prompt with its tags and persona already applied — a full prompt library migrated from a spreadsheet in one pass instead of hundreds of individual clicks. *** ## Tips Step 1 deliberately stops to show you a preview before creating anything — spreadsheets inherited from another tool or another teammate don't always have consistent column names, so it's worth a quick sanity check before hundreds of prompts get created from a misread column. For lists longer than a few hundred rows, ask Claude to process and confirm in batches of 100 rather than all at once — it's easier to catch and fix a mapping error early than to discover it after everything's already been created. This workflow works fine with just a query column — tags and personas are optional. You can always run the Configuration & Maintenance prompts afterward to apply tags in bulk once everything's imported. If you're moving brands, competitors, and personas over as well — not just the prompt list — use the Switch from Another AI Visibility Tool workflow instead; it covers the full migration in one pass. *** For a full account migration, not just the prompt list. Pair this with brand and competitor setup when onboarding from scratch. # Citation Wins Tied to Pipeline Source: https://developers.scrunch.com/mcp/workflows/citation-wins-to-pipeline Match newly-won AI citations and prompt visibility against your CRM's open deals to show which AI visibility gains are touching active revenue. "Our AI visibility improved" is a metric. "Our AI visibility improved on the exact topic three open deals are researching" is a business case. This workflow cross-references Scrunch's newest wins against your CRM's pipeline so you can show, not just say, that the work is connected to revenue. **Tools used in this workflow** | Tool | Required? | Used for | | ----------------------------- | --------------------- | ----------------------------------------------------------- | | Scrunch MCP | Required | Identifying newly-won prompts and citations | | HubSpot MCP or Salesforce MCP | Required (choose one) | Matching wins against open deals and logging the connection | *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find recent AI visibility wins and check whether they touch any open HubSpot deals. Step 1 — Find the wins: Pull prompt variants filtered to brand_present = true for the last [14/30] days. Cross-reference against citation metrics to find prompts where [brand name]'s own domain is now being cited on a topic it wasn't before. List the specific prompts, their tags/topics, and the platforms involved. Step 2 — Match against pipeline: For each topic area from Step 1, search open HubSpot deals for company names or deal notes that mention that topic or a closely related keyword. Step 3 — Log the connection: For any deal that matches, add a note to the deal: "AI visibility update: [brand name] is now appearing in [platform] responses for '[topic]' as of [date]. Citation: [cited URL]. Relevant if this topic comes up in the sales conversation." Step 4 — Summarize: List every deal that got a note, its stage and amount, and the specific visibility win tied to it. This is the evidence for "AI visibility work is touching open pipeline." ``` **What you get:** A short list of open deals with a dated, sourced note showing exactly which AI visibility win is relevant to that conversation — real evidence to bring into a pipeline review or a case for continued investment. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find recent AI visibility wins and check whether they touch any open Salesforce opportunities. Step 1 — Find the wins: Pull prompt variants filtered to brand_present = true for the last [14/30] days. Cross-reference against citation metrics to find prompts where [brand name]'s own domain is now being cited on a topic it wasn't before. List the specific prompts, their tags/topics, and the platforms involved. Step 2 — Match against pipeline: For each topic area from Step 1, search open Salesforce opportunities for account names or opportunity notes that mention that topic or a closely related keyword. Step 3 — Log the connection: For any opportunity that matches, add an activity note: "AI visibility update: [brand name] is now appearing in [platform] responses for '[topic]' as of [date]. Citation: [cited URL]. Relevant if this topic comes up in the sales conversation." Step 4 — Summarize: List every opportunity that got a note, its stage and amount, and the specific visibility win tied to it. This is the evidence for "AI visibility work is touching open pipeline." ``` **What you get:** A short list of open opportunities with a dated, sourced note showing exactly which AI visibility win is relevant to that conversation — real evidence to bring into a pipeline review or a case for continued investment. *** ## Tips Topic-to-deal matching by keyword will surface some false positives, especially for common terms. Have Claude flag its confidence for each match ("strong: deal notes explicitly mention this topic" vs. "weak: same industry, no direct mention") and skim the weak ones before logging. Time this workflow a day or two before a sales or leadership pipeline review — the notes it adds are most useful when they're fresh enough to reference directly in the meeting. If deals don't have structured topic tags, this relies on free-text matching against deal names and notes, which is noisier. Consider adding a simple "primary topic" custom field to deals going forward — it makes every future run of this workflow meaningfully more precise. Include a "Pipeline Impact" section in the Monthly Client Report workflow that pulls directly from the deals this workflow flagged — it's one of the more concrete ROI arguments you can make to a client or to leadership. *** Build the traffic side of the ROI case alongside the pipeline side. Roll pipeline-tied wins into the recurring report you already send. # Competitive Battlecard Generator Source: https://developers.scrunch.com/mcp/workflows/competitive-battlecard Build a per-competitor AI visibility battlecard covering wins, gaps, and talking points, saved to Notion or Google Docs for sales enablement. Sales teams already have product battlecards. This workflow builds the AI-visibility equivalent: where a specific competitor is winning the AI-answer conversation, where you're winning it, and what that means for how a rep should talk about the competitive landscape. **Tools used in this workflow** | Tool | Required? | Used for | | ----------------------------- | --------------------- | ------------------------------------------------- | | Scrunch MCP | Required | Competitive presence, position, and citation data | | Notion MCP or Google Docs MCP | Required (choose one) | Saving the battlecard for sales to reference | *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, build a battlecard against [competitor name] and save it to Notion. Step 1 — Get the competitive picture: Get the competitor ID for [competitor name]. Pull presence and position metrics for both [brand name] and [competitor name] over the last 30 days. Where they're winning: pull prompt variants filtered to competitor_present = [competitor name]'s ID and brand_present = false. Sort by observation count. Take the top 5. Where we're winning: pull prompt variants filtered to brand_present = true and competitor_present = false (for this competitor). Sort by observation count. Take the top 5. Check sentiment for both brands over the same period. Step 2 — Build the battlecard in Notion: Create a page titled "[brand name] vs. [competitor name] — AI Visibility Battlecard" with: - **Overall standing**: presence rate and rank for both brands - **Where they're winning**: the 5 prompts from Step 1, with a one-line note on what to say if this comes up ("We're not currently cited on this specific question, but our strength is...") - **Where we're winning**: the 5 prompts from Step 1, framed as proof points a rep can cite directly - **Sentiment comparison**: how each brand is described when mentioned - **Talking point summary**: 2-3 sentences a rep can use verbatim when a prospect brings up this competitor Step 3 — Confirm: Give me the Notion page link and the one most important talking point from it. ``` **What you get:** A Notion battlecard with concrete, sourced examples on both sides of the competitive comparison — not just "we're ahead" or "they're ahead," but the specific prompts and platforms behind that claim. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, build a battlecard against [competitor name] and save it to Google Docs. Step 1 — Get the competitive picture: Get the competitor ID for [competitor name]. Pull presence and position metrics for both [brand name] and [competitor name] over the last 30 days. Where they're winning: pull prompt variants filtered to competitor_present = [competitor name]'s ID and brand_present = false. Sort by observation count. Take the top 5. Where we're winning: pull prompt variants filtered to brand_present = true and competitor_present = false (for this competitor). Sort by observation count. Take the top 5. Check sentiment for both brands over the same period. Step 2 — Build the battlecard in Google Docs: Create a document titled "[brand name] vs. [competitor name] — AI Visibility Battlecard" with: - **Overall standing**: presence rate and rank for both brands - **Where they're winning**: the 5 prompts from Step 1, with a one-line note on what to say if this comes up ("We're not currently cited on this specific question, but our strength is...") - **Where we're winning**: the 5 prompts from Step 1, framed as proof points a rep can cite directly - **Sentiment comparison**: how each brand is described when mentioned - **Talking point summary**: 2-3 sentences a rep can use verbatim when a prospect brings up this competitor Step 3 — Confirm: Give me the Google Docs link and the one most important talking point from it. ``` **What you get:** A Google Docs battlecard with concrete, sourced examples on both sides of the competitive comparison — not just "we're ahead" or "they're ahead," but the specific prompts and platforms behind that claim. *** ## Tips Run this once per competitor rather than trying to cover all of them in one document — a battlecard that's specific to one rival is more usable in the moment than a single sprawling document covering five. Re-run this quarterly, or immediately after a Competitor Share of Voice report shows a meaningful rank change against that specific competitor. A battlecard with 6-month-old data is worse than no battlecard — reps will repeat stale claims. If a competitor is winning on presence, position, and sentiment, don't force a "where we're winning" section that isn't true — say so directly and reframe the talking points around differentiation that isn't visibility-based (pricing, service, specific features) instead. The same structure works as an input to the content team — "where they're winning" is effectively a prioritized content gap list specific to one competitor, and pairs directly with the Content Brief Handoff to Design workflow. *** Run this first to decide which competitor deserves a battlecard. Track the underlying numbers over time instead of a point-in-time battlecard. # Competitor Share of Voice, Ranked Source: https://developers.scrunch.com/mcp/workflows/competitor-share-of-voice Rank every tracked competitor by how often they appear in AI responses, find where they're displacing you, and surface the specific prompts to reclaim. Paste this in to get a full competitive ranking — who's ahead of you, which topic areas they're winning, and which prompts you should target to close the gap. **Tools used in this workflow** | Tool | Required? | Used for | | ----------- | --------- | -------------------------------------------------- | | Scrunch MCP | Required | Competitive presence data, displacement analysis | | Slack MCP | Optional | Posting the share of voice table to a team channel | *** ```text theme={null} For [brand name] in Scrunch, run a full competitive share of voice analysis. Step 1 — Build the rankings: 1. List all tracked competitors for [brand name] 2. Get presence metrics for [brand name] and all competitors for the last 30 days, with competitors included in the results 3. For each brand, calculate share of voice: their presence count as a percentage of total tracked variants 4. Rank all brands — [brand name] and every competitor — by share of voice Step 2 — Map the displacement: For each competitor that outranks [brand name]: - Pull the specific prompts where that competitor appears and [brand name] does not - Sort by observation count — these are the highest-stakes losses - Identify which topic areas and funnel stages they're winning in - Note whether their advantage is concentrated on specific AI platforms or consistent across all Step 3 — Find defensible positions: Identify the prompts where [brand name] appears and the top 3 competitors do not. These are the positions to protect. Step 4 — Deliver the output: Present: - A ranked share of voice table (all brands, percentage, rank) - For each competitor ahead of [brand name]: top 3 topic areas where they're winning + top 3 highest-observation prompts we should reclaim - A one-paragraph competitive summary: are we the leader, challenger, or lagging? What is the single most impactful action to improve our rank? Then post this to [#channel-name] on Slack: "📊 [brand name] AI Share of Voice — [date] Our rank: [#X] of [total brands tracked] Our share of voice: [X]% [Competitor name] leads at [Y]% — biggest gap: [top topic area] Recommended action: [one sentence]" ``` ```text theme={null} For [brand name] in Scrunch, run a competitive share of voice analysis. 1. List all tracked competitors 2. Get presence metrics for [brand name] and all competitors for the last 30 days — include competitors in the results 3. Calculate share of voice for each: presence count as a percentage of total tracked variants 4. Rank all brands by share of voice For each competitor that outranks [brand name]: - What topics and funnel stages are they winning in? - Which platform is their advantage most concentrated on? - What are the top 3 specific prompts (by observation count) where they appear and we don't? End with a one-paragraph competitive summary and one recommended action. ``` *** ## Tips If you want to focus on a single competitor rather than all of them, use this prompt from the Prompt Library instead: "See Where a Competitor Is Beating You." It goes deeper on the displacement and topic breakdown for a specific brand. The share of voice table from Step 4 can be pasted directly into the Monthly Client Report workflow. Run competitive SOV first, then run the monthly report — Claude will have the competitive context in memory for the session. The prompts where you appear and competitors don't are your moat. Note which pages and content types are driving those wins — those are your highest-performing AI assets to protect, expand, and use as a model for other content. *** Pair this with gap analysis to see which gaps are actually being won by competitors. Include this competitive data in a full monthly report saved to Notion. # Live Competitor Tracker Spreadsheet Source: https://developers.scrunch.com/mcp/workflows/competitor-tracker-spreadsheet Build a spreadsheet of share-of-voice by competitor that you re-run on a cadence to append each period's snapshot into a running trend tab. A one-time competitive report goes stale the day after you send it. This workflow builds a spreadsheet that's designed to be re-run — each time you paste the prompt back in, it appends a new row instead of starting over, so you end up with a real trend line instead of a pile of disconnected screenshots. **Tools used in this workflow** | Tool | Required? | Used for | | ------------------------------ | --------------------- | -------------------------------------------------------- | | Scrunch MCP | Required | Competitive presence data and share-of-voice calculation | | Google Sheets MCP or Excel MCP | Required (choose one) | Storing the running trend and rendering the chart | *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, update my competitive share-of-voice tracker in Google Sheets. Step 1 — Pull this period's numbers: List all tracked competitors for [brand name]. Get presence metrics for [brand name] and all competitors for the last 30 days, with competitors included in the results. Calculate each brand's share of voice: their presence count as a percentage of total tracked variants. Step 2 — Update the spreadsheet: Open [spreadsheet name or URL]. If a tab called "SOV Trend" doesn't exist, create one with columns: Date, Brand, Share of Voice %, Rank. Append one row per brand for today's date — [brand name] plus every competitor — to the "SOV Trend" tab. Don't overwrite existing rows; this should be additive so the sheet builds a history over time. Step 3 — Refresh the chart: If a line chart plotting Share of Voice % over Date, grouped by Brand, doesn't already exist on a "Chart" tab, create one. If it exists, confirm it's picking up the new rows automatically. Step 4 — Summarize what moved: Compare today's rank and share of voice for [brand name] against the previous entry in the sheet (if any). Call out: did our rank change? Did any competitor pass us or fall behind? By how much? ``` **What you get:** A living spreadsheet with one tab holding the full historical trend and a chart that updates itself as you add rows — re-run this weekly or monthly and watch the competitive picture accumulate instead of re-explaining it from scratch each time. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, update my competitive share-of-voice tracker in Excel. Step 1 — Pull this period's numbers: List all tracked competitors for [brand name]. Get presence metrics for [brand name] and all competitors for the last 30 days, with competitors included in the results. Calculate each brand's share of voice: their presence count as a percentage of total tracked variants. Step 2 — Update the workbook: Open [workbook name or path]. If a worksheet called "SOV Trend" doesn't exist, create one with columns: Date, Brand, Share of Voice %, Rank. Append one row per brand for today's date — [brand name] plus every competitor — to the "SOV Trend" sheet. Don't overwrite existing rows; this should be additive so the workbook builds a history over time. Step 3 — Refresh the chart: If a line chart plotting Share of Voice % over Date, grouped by Brand, doesn't already exist, create one on its own worksheet. If it exists, confirm the data range covers the newly added rows. Step 4 — Summarize what moved: Compare today's rank and share of voice for [brand name] against the previous entry in the workbook (if any). Call out: did our rank change? Did any competitor pass us or fall behind? By how much? ``` **What you get:** A living workbook with one sheet holding the full historical trend and a chart that updates as you add rows — re-run this weekly or monthly and watch the competitive picture accumulate instead of re-explaining it from scratch each time. *** ## Tips Weekly is enough to catch real movement without adding noise — share of voice rarely swings meaningfully day to day. Monthly works fine for a slower-moving competitive set. Pick a cadence and stick to it; consistent spacing between rows makes the trend line easier to read than irregular snapshots. On the very first run, the sheet won't have a previous entry to compare against — that's expected. Claude will just populate today's row and skip Step 4's comparison. The trend becomes useful starting with the second run. Extend Step 1 to also pull sentiment or citation share per brand, and add matching columns to the tracker tab. The same append-only pattern works for any metric — the key is keeping Date and Brand as the two columns every new metric joins against. Once the trend tab has a few weeks of history, ask Claude to pull the latest 8-12 rows and summarize them as a short written update — that's a safer thing to paste into a client email or Slack channel than sharing edit access to the live sheet. *** Run the full one-time analysis (displacement, defensible positions) before setting up the recurring tracker. Turn this same competitive data into sales-facing battlecards instead of a trend sheet. # Content Brief Handoff to Design Source: https://developers.scrunch.com/mcp/workflows/content-brief-to-design Turn a Scrunch visibility gap into a structured content brief and hand it to your design or content team as a FigJam board, ready to move into layout. The data on a visibility gap usually lives in Scrunch, but the people who design and lay out the content that fixes it live in Figma. This workflow bridges the two: it turns a gap into a structured brief and drops it directly into a FigJam board your design team already works in. **Tools used in this workflow** | Tool | Required? | Used for | | ----------- | --------- | -------------------------------------------------------- | | Scrunch MCP | Required | Identifying the gap and pulling supporting citation data | | Figma MCP | Required | Creating the FigJam brief board | *** ```text theme={null} For [brand name] in Scrunch, turn our biggest content gap into a design-ready brief in FigJam. Step 1 — Find the gap and its context: Get all tags. For each tag, get presence metrics for the last 30 days and calculate the presence rate. Identify the tag with the lowest presence rate that has at least [10] observations. For that tag: - List the top 5 specific prompts where [brand name] is absent, sorted by observation count - Check citations for those prompts: which competitor or third-party domains are getting cited instead? - Note the funnel stage these prompts fall into (awareness, consideration, decision) Step 2 — Build the brief in FigJam: Create a new FigJam board called "[topic area] — Content Brief" with these sections, one per sticky-note cluster: - **The gap**: [brand name]'s current presence rate on this topic and why it matters - **What to answer**: the specific questions from the 5 prompts in Step 1, rewritten as headers a piece of content could directly address - **Who's winning it now**: the competitor or third-party sources currently cited, and what they're doing that seems to be working - **Funnel stage & tone**: whether this content should read as introductory (awareness) or comparative/decisive (consideration/decision), which affects layout and depth - **Success metric**: presence rate on this tag should improve within 30-60 days of publishing Step 3 — Confirm: Give me the FigJam board link and a one-line summary of what's on it. ``` **What you get:** A FigJam board with the gap, the specific questions to answer, the competitive context, and the tone/funnel guidance — everything a designer or content lead needs to start laying out the piece, without translating a data export themselves. *** ## Tips If your content team writes first and designs later, use the Create Content That Gets AI Citations workflow instead — it's built for drafting the content itself rather than briefing a layout. Ask Claude to repeat Step 1 for the next 2-3 lowest-performing tags and add each as its own section on the same FigJam board, so design can see and prioritize across several briefs at once rather than one gap at a time. Resist the urge to add every data point Scrunch can surface — a brief with 5 questions and one competitive callout gets used; a brief with 20 data points gets skimmed once and ignored. Keep Step 1 focused on the single tag with the clearest story. Once the content ships, use the Track Whether It Worked step from Create Content That Gets AI Citations to check whether the presence rate on this tag actually improved. *** For teams that draft the content directly instead of handing off a design brief. For handing the gap off as a tracked ticket instead of a FigJam brief. # Stage Content Tasks for Review Source: https://developers.scrunch.com/mcp/workflows/content-task-handoff MCP workflow that turns a Scrunch content gap into a fully-briefed Linear, Jira, GitHub, or Asana ticket for the teammate who owns publishing. Not everyone who monitors Scrunch has the permissions — or the bandwidth — to publish content themselves. This workflow closes that gap: pull the visibility data, have Claude draft a fully-contextualized task, and create it in your team's project management tool so the right person can pick it up. **Tools used in this workflow** | Tool | Required? | Used for | | ---------------------------------- | --------------------- | ------------------------------------------------------- | | Scrunch MCP | Required | Identifying the content gap and providing brief context | | Linear / Jira / GitHub / Asana MCP | Required (choose one) | Creating the task for the content owner | Choose your project management tool in the tabs below. *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find the highest-priority content gap and create a task for the content team. Step 1 — Find the gap: Get all tags. For each tag, pull presence metrics for the last 30 days and calculate the presence rate. Identify the tag with the lowest presence rate that has at least [10] observations. For that tag: - List the 5 specific prompts where [brand name] is absent, sorted by observation count - Check citations: what share is going to competitors vs. third parties vs. brand-owned? - Is any tracked competitor consistently appearing in these prompts? Which one? Step 2 — Create a Linear issue in [team name]: Title: "AI Visibility Gap: [topic area] — content needed" Description: ## What Scrunch found [Brand name] has [X]% presence on [topic] — one of our lowest-performing areas. AI engines are answering questions in this space but not citing our content. ## The specific prompts we're missing [List the 5 prompts from Step 1 with observation counts] ## Who's winning instead [Competitor name or third-party domain] appears in [X]% of these responses. ## What needs to happen [New content / update to existing page] that directly answers these questions. See the Create Content for AI Citations workflow for how to structure it: https://developers.scrunch.com/mcp/workflows/create-content-for-citations ## Success metric Track this tag in Scrunch after publishing — presence rate should increase within 30–60 days. Labels: ai-visibility, content Priority: [High / Medium based on observation count] Assignee: [name or email] ``` **What you get:** A Linear issue with the full gap context already written — topic, missing prompts, competitor situation, and a clear brief for whoever picks it up. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find the highest-priority content gap and create a task for the content team. Step 1 — Find the gap: Get all tags. For each tag, pull presence metrics for the last 30 days and calculate the presence rate. Identify the tag with the lowest presence rate that has at least [10] observations. For that tag: - List the 5 specific prompts where [brand name] is absent, sorted by observation count - Check citations: what share is going to competitors vs. third parties vs. brand-owned? - Is any tracked competitor consistently appearing in these prompts? Which one? Step 2 — Create a Jira issue in project [PROJECT-KEY]: Issue type: Task Summary: "AI Visibility Gap: [topic area] — content needed" Description (use Jira markup): h2. What Scrunch found [Brand name] has [X]% presence on [topic] — one of our lowest-performing areas. AI engines are answering questions in this space but not citing our content. h2. The specific prompts we're missing [List the 5 prompts from Step 1 with observation counts] h2. Who's winning instead [Competitor name or third-party domain] appears in [X]% of these responses. h2. What needs to happen [New content / update to existing page] that directly answers these questions. See the Create Content for AI Citations workflow: https://developers.scrunch.com/mcp/workflows/create-content-for-citations h2. Success metric Track this tag in Scrunch after publishing — presence rate should increase within 30–60 days. Labels: ai-visibility, content Priority: [High / Medium based on observation count] Assignee: [name or email] ``` **What you get:** A Jira task with the full gap context already written — topic, missing prompts, competitor situation, and a clear brief for whoever picks it up. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find the highest-priority content gap and create a GitHub issue for the content team. Step 1 — Find the gap: Get all tags. For each tag, pull presence metrics for the last 30 days and calculate the presence rate. Identify the tag with the lowest presence rate that has at least [10] observations. For that tag: - List the 5 specific prompts where [brand name] is absent, sorted by observation count - Check citations: what share is going to competitors vs. third parties vs. brand-owned? - Is any tracked competitor consistently appearing in these prompts? Which one? Step 2 — Create a GitHub issue in [owner/repo]: Title: "AI Visibility Gap: [topic area] — content needed" Body: ## What Scrunch found [Brand name] has [X]% presence on [topic] — one of our lowest-performing areas. AI engines are answering questions in this space but not citing our content. ## The specific prompts we're missing | Prompt | Observations | |---|---| [List the 5 prompts from Step 1] ## Who's winning instead [Competitor name or third-party domain] appears in [X]% of these responses. ## What needs to happen [New content / update to existing page] that directly answers these questions. See the [Create Content for AI Citations](https://developers.scrunch.com/mcp/workflows/create-content-for-citations) workflow for how to structure it. ## Success metric Track this tag in Scrunch after publishing — presence rate should increase within 30–60 days. Labels: ai-visibility, content Assignees: [username] ``` **What you get:** A GitHub issue with the full gap context already written — topic, missing prompts, competitor situation, and a clear brief for whoever picks it up. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find the highest-priority content gap and create a task for the content team. Step 1 — Find the gap: Get all tags. For each tag, pull presence metrics for the last 30 days and calculate the presence rate. Identify the tag with the lowest presence rate that has at least [10] observations. For that tag: - List the 5 specific prompts where [brand name] is absent, sorted by observation count - Check citations: what share is going to competitors vs. third parties vs. brand-owned? - Is any tracked competitor consistently appearing in these prompts? Which one? Step 2 — Create an Asana task in project [project name]: Name: "AI Visibility Gap: [topic area] — content needed" Description: What Scrunch found: [Brand name] has [X]% presence on [topic] — one of our lowest-performing areas. AI engines are answering questions in this space but not citing our content. The specific prompts we're missing: [List the 5 prompts from Step 1 with observation counts] Who's winning instead: [Competitor name or third-party domain] appears in [X]% of these responses. What needs to happen: [New content / update to existing page] that directly answers these questions. See the Create Content for AI Citations workflow: https://developers.scrunch.com/mcp/workflows/create-content-for-citations Success metric: Track this tag in Scrunch after publishing — presence rate should increase within 30–60 days. Assignee: [name or email] Due date: [date] Tags: ai-visibility, content ``` **What you get:** An Asana task with the full gap context already written — topic, missing prompts, competitor situation, and a clear brief for whoever picks it up. *** ## Tips After Step 1, ask: "Repeat this for the next 2 lowest-performing tags." You'll get 3 gap summaries. Then create a ticket for each using the same tab — one conversation, three tasks created and assigned. Add this line to the ticket description: "Scrunch tag: \[tag name] — filter to this tag in the dashboard for the full data." Whoever picks up the task can open Scrunch directly to the relevant data without running the analysis again. If Scrunch shows you're present sometimes but inconsistently (presence rate 10–40%), you likely need to update an existing page rather than create something new. Add this to Step 1: "Does \[brand name] have any presence in this tag at all, or is it zero? If partial, what's the presence rate?" Zero presence usually means missing content; partial presence usually means weak content. Once the content is published, add the URL to the ticket and check Scrunch in 30 days. Use the Track Whether It Worked step from the Create Content for AI Citations workflow to close the loop. *** The workflow for whoever picks up the ticket — pull the brief from Scrunch, generate the content, publish through your CMS. Run a deeper gap analysis first and save it to Notion or Google Docs before creating tasks. # Create Content That Gets AI Citations Source: https://developers.scrunch.com/mcp/workflows/create-content-for-citations Use Scrunch citation gaps to identify what to write, generate content optimized for AI retrieval, and publish it through your CMS — all in one workflow. Most content strategies are built for search engines. This workflow builds content for AI engines. It starts with Scrunch data to find the exact questions AI is answering without citing your pages, generates content specifically structured to be cited, and publishes it directly through your CMS. The result: content targeted at the prompts where your competitors are getting cited and you aren't. **Tools used in this workflow** | Tool | Required? | Used for | | ----------------- | ----------- | ------------------------------------------------------------ | | Scrunch MCP | Required | Identifying citation gaps and the specific prompts to target | | CMS MCP | Recommended | Publishing the generated content directly | | Brand style guide | Optional | Paste into the prompt or attach as context | Choose your CMS in the tabs below. Supported integrations: Sanity, WordPress, HubSpot, and any CMS with an MCP connector. No CMS connected? Use the **Generate only** tab to get the content in the chat and paste it yourself. *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find the highest-priority citation gap and create AI-optimized content for it. Step 1 — Find the gap: Get citation metrics for the last 30 days. Get all tags and calculate the citation rate from [brand domain] for each — variants with brand_present = true and a citation pointing to [brand domain] divided by total variants. Rank tags by citation rate lowest to highest. For the lowest-performing tag, list the prompts where brand_present = false, sorted by observation count. Note what sources are being cited instead. Step 2 — Get the brief: Identify the single highest-priority topic: most prompts where we're absent + highest observation counts + clearest commercial relevance. Give me a content brief: - The 5–8 specific questions this page should directly answer - What the competing or cited content is doing that ours isn't - The recommended format (article, comparison page, FAQ, landing page, etc.) - What specific facts, figures, or claims would make this page more citable than what's currently appearing Step 3 — Write the content: Write a [blog post / guide / comparison page / FAQ page] for [brand name] on the topic identified above. Structure it to be cited by AI engines: - Open with a direct, concise answer to the primary question — 2–3 sentences an AI could extract and cite verbatim - Use clear H2 and H3 headings that match how users phrase these questions in AI assistants - Include specific, factual claims with numbers, dates, or rankings where possible — generic statements don't get cited - Answer each of the specific questions from Step 2 directly and completely - Avoid marketing language in the factual sections — AI cites descriptive, informational content - Target length: [800–1,500 words] unless the topic warrants more depth [Optional: follow this brand style guide: paste guidelines here] Step 4 — Publish to Sanity: Publish this content as a new Sanity document: - Document type: [article / blog-post / page — match your schema] - Title: [SEO-optimized title for the topic] - Slug: [url-friendly-slug] - Body: [the content generated above] - SEO meta description: Write a 150-character meta description focused on the primary question this page answers - Status: [draft / published] - [Any other schema fields relevant to your Sanity setup] ``` **What you get:** A new Sanity document, set to draft, ready for your review before publishing. The content is structured specifically to be extracted and cited by AI engines — direct answers up front, factual specificity throughout, headings that match real AI queries. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find the highest-priority citation gap and create AI-optimized content for it. Step 1 — Find the gap: Get citation metrics for the last 30 days. Get all tags and calculate the citation rate from [brand domain] for each — variants with brand_present = true and a citation pointing to [brand domain] divided by total variants. Rank tags by citation rate lowest to highest. For the lowest-performing tag, list the prompts where brand_present = false, sorted by observation count. Note what sources are being cited instead. Step 2 — Get the brief: Identify the single highest-priority topic: most prompts where we're absent + highest observation counts + clearest commercial relevance. Give me a content brief: - The 5–8 specific questions this page should directly answer - What the competing or cited content is doing that ours isn't - The recommended format (article, comparison page, FAQ, landing page, etc.) - What specific facts, figures, or claims would make this page more citable than what's currently appearing Step 3 — Write the content: Write a [blog post / guide / comparison page / FAQ page] for [brand name] on the topic identified above. Structure it to be cited by AI engines: - Open with a direct, concise answer to the primary question — 2–3 sentences an AI could extract and cite verbatim - Use clear H2 and H3 headings that match how users phrase these questions in AI assistants - Include specific, factual claims with numbers, dates, or rankings where possible — generic statements don't get cited - Answer each of the specific questions from Step 2 directly and completely - Avoid marketing language in the factual sections — AI cites descriptive, informational content - Target length: [800–1,500 words] unless the topic warrants more depth [Optional: follow this brand style guide: paste guidelines here] Step 4 — Create a WordPress draft: Create a new WordPress post with this content: - Title: [SEO-optimized title] - Content: [the generated article, formatted as WordPress blocks] - Status: draft - Category: [category name] - Tags: [relevant tags] - SEO meta description: [150-character description focused on the primary question] Set it as a draft so I can review before publishing. ``` **What you get:** A WordPress draft ready for your review. The content is structured specifically to be extracted and cited by AI engines — direct answers up front, factual specificity throughout, headings that match real AI queries. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, find the highest-priority citation gap and create AI-optimized content for it. Step 1 — Find the gap: Get citation metrics for the last 30 days. Get all tags and calculate the citation rate from [brand domain] for each — variants with brand_present = true and a citation pointing to [brand domain] divided by total variants. Rank tags by citation rate lowest to highest. For the lowest-performing tag, list the prompts where brand_present = false, sorted by observation count. Note what sources are being cited instead. Step 2 — Get the brief: Identify the single highest-priority topic: most prompts where we're absent + highest observation counts + clearest commercial relevance. Give me a content brief: - The 5–8 specific questions this page should directly answer - What the competing or cited content is doing that ours isn't - The recommended format (article, comparison page, FAQ, landing page, etc.) - What specific facts, figures, or claims would make this page more citable than what's currently appearing Step 3 — Write the content: Write a [blog post / guide / comparison page / FAQ page] for [brand name] on the topic identified above. Structure it to be cited by AI engines: - Open with a direct, concise answer to the primary question — 2–3 sentences an AI could extract and cite verbatim - Use clear H2 and H3 headings that match how users phrase these questions in AI assistants - Include specific, factual claims with numbers, dates, or rankings where possible — generic statements don't get cited - Answer each of the specific questions from Step 2 directly and completely - Avoid marketing language in the factual sections — AI cites descriptive, informational content - Target length: [800–1,500 words] unless the topic warrants more depth [Optional: follow this brand style guide: paste guidelines here] Step 4 — Create a HubSpot blog post: Create a new HubSpot blog post: - Title: [title] - Body: [generated content] - Meta description: [150-character description focused on the primary question] - Campaign: [campaign name if applicable] - Publish state: DRAFT ``` **What you get:** A HubSpot blog draft ready for review. The content is structured specifically to be extracted and cited by AI engines — direct answers up front, factual specificity throughout, headings that match real AI queries. Works for Webflow, Ghost, Contentful, or any CMS with an MCP connector. Replace the bracketed values, then paste. ```text theme={null} For [brand name] in Scrunch, find the highest-priority citation gap and create AI-optimized content for it. Step 1 — Find the gap: Get citation metrics for the last 30 days. Get all tags and calculate the citation rate from [brand domain] for each — variants with brand_present = true and a citation pointing to [brand domain] divided by total variants. Rank tags by citation rate lowest to highest. For the lowest-performing tag, list the prompts where brand_present = false, sorted by observation count. Note what sources are being cited instead. Step 2 — Get the brief: Identify the single highest-priority topic: most prompts where we're absent + highest observation counts + clearest commercial relevance. Give me a content brief: - The 5–8 specific questions this page should directly answer - What the competing or cited content is doing that ours isn't - The recommended format (article, comparison page, FAQ, landing page, etc.) - What specific facts, figures, or claims would make this page more citable than what's currently appearing Step 3 — Write the content: Write a [blog post / guide / comparison page / FAQ page] for [brand name] on the topic identified above. Structure it to be cited by AI engines: - Open with a direct, concise answer to the primary question — 2–3 sentences an AI could extract and cite verbatim - Use clear H2 and H3 headings that match how users phrase these questions in AI assistants - Include specific, factual claims with numbers, dates, or rankings where possible — generic statements don't get cited - Answer each of the specific questions from Step 2 directly and completely - Avoid marketing language in the factual sections — AI cites descriptive, informational content - Target length: [800–1,500 words] unless the topic warrants more depth [Optional: follow this brand style guide: paste guidelines here] Step 4 — Publish to [CMS name]: Create a new [content type] in [CMS name] with: - Title: [title] - Body/Content: [the generated article] - Meta description: Write a 150-character description focused on the primary question this page answers - Status: draft ``` **No MCP connector?** After Step 3, ask Claude to format the output as HTML or Markdown ready for copy-paste into your CMS editor instead. No CMS connected? This tab gives you the full analysis and content in the chat — paste it wherever you need it. ```text theme={null} For [brand name] in Scrunch, find the highest-priority citation gap and write AI-optimized content to fill it. Step 1 — Find the gap: Get citation metrics for the last 30 days. Get all tags and calculate the citation rate from [brand domain] for each — variants with brand_present = true and a citation pointing to [brand domain] divided by total variants. Rank tags by citation rate lowest to highest. For the lowest-performing tag, list the prompts where brand_present = false, sorted by observation count. Note what sources are being cited instead. Step 2 — Get the brief: Identify the single highest-priority topic: most prompts where we're absent + highest observation counts + clearest commercial relevance. Give me a content brief: - The 5–8 specific questions this page should directly answer - What the competing or cited content is doing that ours isn't - The recommended format (article, comparison page, FAQ, landing page, etc.) - What specific facts, figures, or claims would make this page more citable Step 3 — Write the content: Write a [blog post / guide / comparison page / FAQ page] for [brand name] on the topic identified above. Structure it to be cited by AI engines: - Open with a direct, concise answer to the primary question — 2–3 sentences an AI could extract and cite verbatim - Use clear H2 and H3 headings that match how users phrase these questions in AI assistants - Include specific, factual claims with numbers, dates, or rankings where possible - Answer each of the specific questions from Step 2 directly and completely - Avoid marketing language in the factual sections - Target length: [800–1,500 words] unless the topic warrants more depth Format the final output as Markdown, ready to paste into any CMS or doc editor. [Optional: follow this brand style guide: paste guidelines here] ``` *** ## Track whether it worked After publishing, save the URL and check back in Scrunch after 30–60 days. ```text theme={null} For [brand name] in Scrunch, check whether our new content at [published URL] is being cited. Pull citation metrics for the tag [topic tag]. Has the citation rate for [brand domain] improved compared to last month? Are the specific prompts from the gap analysis now showing brand_present = true? ``` This closes the loop: Scrunch identified the gap, content filled it, Scrunch confirms whether it worked. *** ## Tips AI engines cite pages that **directly answer a specific question** with a clear, extractable statement. The most citable content has: a direct answer in the first paragraph, factual specificity (numbers, comparisons, rankings), question-matching headers, and no ambiguity about what the page is claiming. Generic "thought leadership" rarely gets cited — specific, opinionated, factual writing does. If Scrunch shows that a topic is partially covered (you appear sometimes but not consistently), you may not need new content — you need to update an existing page. In Step 3, change the instruction to: "Rewrite and expand the \[existing page title] to more directly answer these specific questions from Scrunch. Focus on adding the citable, factual sections that are currently missing." After Step 2, ask Claude: "Repeat Step 2 for the next 3 lowest-performing tags and give me a prioritized brief for each." You'll get 4 content briefs in one session. Then run Step 3 for each in the same conversation or batch them into separate sessions. Add this to Step 2: "For the top 3 competitor or third-party URLs being cited in this topic gap, describe what those pages cover that ours don't. What specific angles, data points, or question-types do they address that we're missing?" This makes your content brief much sharper. Paste style guidelines directly into Step 3 after the main prompt. For a longer style guide (5,000+ words), attach it as a file or paste it in a prior message before running the workflow. *** Make sure you're tracking the right prompts before creating content — use SEO keywords to find gaps in your Scrunch coverage. Not the one who publishes? Create a briefed ticket in Linear, Jira, GitHub, or Asana for whoever does. # Executive Explorer Dashboard Source: https://developers.scrunch.com/mcp/workflows/executive-explorer-dashboard Assemble a saved Scrunch Explorer dashboard covering presence, position, sentiment, and citations in one conversation, and get a shareable link back. Skip the slide deck when a live, clickable view will do. This workflow has Claude assemble a multi-tile Explorer dashboard directly from a plain-English brief — no manual chart building required — and hand you back a link you can share or bookmark. **Tools used in this workflow** | Tool | Required? | Notes | | ----------- | --------- | --------------------------------------------------------------------------------------------- | | Scrunch MCP | Required | Uses `create_explorer_dashboard`, which writes a saved dashboard to your Scrunch organization | This workflow uses a write operation. Your AI agent will confirm the tile list before saving the dashboard. *** ```text theme={null} For [brand name] in Scrunch, build an executive Explorer dashboard covering the last [30/90] days. Step 1 — Propose the tiles: Put together a dashboard with 5-6 tiles mixing headline numbers and trend charts: 1. A card tile: current overall presence rate 2. A line chart: presence rate over time, with [top competitor] overlaid for comparison 3. A card tile: current share of voice rank among tracked competitors 4. A line chart: sentiment breakdown (positive/mixed/negative) over time 5. A bar chart: citations broken down by owner (brand, competitor, third-party) 6. A line chart: position (top/middle/bottom) over time Show me the proposed tile list before saving anything. Step 2 — Save it: Once I confirm, create the dashboard named "[brand name] Executive Overview — [month/year]" with those tiles and give me the link. Step 3 — Summarize: In 2-3 sentences, tell me what the dashboard shows at a glance right now — is the overall picture improving, flat, or declining? ``` **What you get:** A saved, shareable Explorer dashboard link plus a short plain-English read on what it currently shows — refresh the link any time rather than rebuilding a deck from scratch. *** ## Tips For a client-facing dashboard, keep the tile count to 5-6 and favor card tiles for headline numbers — clients want a fast read, not a data exploration surface. For an internal team dashboard, add more granular breakdowns (per-platform, per-tag) since the audience is more likely to dig in. `create_explorer_dashboard` always creates a new saved dashboard rather than editing one in place. If you're refreshing a recurring dashboard, either keep using the same link (dashboards reflect live data automatically, so tiles update without a rebuild) or explicitly ask for a new dashboard only when the tile mix itself needs to change. If you just want to sanity-check one chart before committing to a full dashboard, ask Claude to generate a single Explorer chart first. Once you like how a metric looks, fold it into the dashboard tile list in Step 1. Drop the dashboard link into a QBR deck appendix, a stakeholder email, or a Slack pin — it's a live view, so anyone with the link always sees current data without needing you to re-run anything. *** Use this dashboard link as a live companion to a static QBR deck. For a written narrative report instead of a live clickable dashboard. # Find Visibility Gaps Worth Fixing Source: https://developers.scrunch.com/mcp/workflows/find-visibility-gaps MCP workflow to surface your weakest AI visibility topics, identify the specific prompts you're losing, and ship a prioritized content action plan to Notion. This workflow identifies your weakest topic areas, surfaces the specific queries you're losing, checks what competitors and third-party sources are filling the gap, and builds a Notion tracker with content recommendations — all in one go. **Tools used in this workflow** | Tool | Required? | Used for | | -------------------- | --------- | ---------------------------------------------------------- | | Scrunch MCP | Required | Pulling tag-level presence, gap prompts, and citation data | | Notion MCP | Optional | Creating a prioritized gap tracker database | | Google Workspace MCP | Optional | Saving the gap analysis as a Google Doc | Use the **Scrunch only** tab if you don't have Notion or Google Workspace connected. *** Replace the bracketed values, then paste. ```text theme={null} For [brand name] in Scrunch, run a visibility gap analysis and build a prioritized action plan. Step 1 — Find the weakest topic areas: Get all tags configured for [brand name]. For each tag, pull presence metrics for the last 30 days. Rank tags by presence rate from lowest to highest. Identify the 3 tags with the lowest presence — these are the priority investment areas. Step 2 — Surface the specific missing prompts: For each of the 3 lowest-performing tags: - List the prompt variants where [brand name] is not present in the last 30 days - Show: prompt text, platform, observation count - Sort by observation count — the most-observed missing prompts are the most urgent - Get citation metrics for that tag: what share of citations are brand-owned vs. competitor vs. third-party? Step 3 — Check the competitive situation: For the lowest-performing tag, check: are any tracked competitors showing up in these prompts where [brand name] isn't? Which competitor appears most in this gap area? Step 4 — Build the Notion tracker: Create a Notion database titled "[brand name] Visibility Gap Tracker — [month year]" with these columns: Topic Area, Presence Rate, Gap Count, Competitor Winning, Citation Type, Priority, Status. Create one row per gap tag. Set Priority based on: lowest presence rate combined with highest total observation count = most urgent. Inside each row's page, write: - The 5 highest-priority missing prompts for that topic area (with prompt text and observation count) - What competitor or third-party content is filling the gap - 3 specific content recommendations to close it — whether this is existing content to optimize or something net-new ``` **What you get:** A Notion database you can share with content and SEO teams, with each gap area documented, ranked by urgency, and loaded with specific recommendations. No need to interpret the numbers — Claude does that for you. Replace the bracketed values, then paste. ```text theme={null} For [brand name] in Scrunch, run a visibility gap analysis and save the results as a Google Doc. Step 1 — Find the weakest topic areas: Get all tags configured for [brand name]. For each tag, pull presence metrics for the last 30 days. Rank tags by presence rate from lowest to highest. Identify the 3 tags with the lowest presence — these are the priority investment areas. Step 2 — Surface the specific missing prompts: For each of the 3 lowest-performing tags: - List the prompt variants where [brand name] is not present in the last 30 days - Show: prompt text, platform, observation count - Sort by observation count — the most-observed missing prompts are the most urgent - Get citation metrics for that tag: what share of citations are brand-owned vs. competitor vs. third-party? Step 3 — Check the competitive situation: For the lowest-performing tag, check: are any tracked competitors showing up in these prompts where [brand name] isn't? Which competitor appears most in this gap area? Step 4 — Save to Google Docs: Create a new Google Doc titled "[brand name] Visibility Gap Analysis — [month year]" in [folder name or Drive location] with this structure: ## Summary The 3 highest-priority gap areas, ranked by urgency, with a one-sentence description of each. ## Gap Area 1: [Tag Name] - Presence rate: [X]% - Top missing prompts (with observation counts) - Competitor winning this space: [name] - Citation breakdown: [brand / competitor / third-party split] - 3 content recommendations to close the gap ## Gap Area 2: [Tag Name] [same structure] ## Gap Area 3: [Tag Name] [same structure] ## Recommended Next Steps Prioritized action list — what to create or optimize first, and why. ``` **What you get:** A Google Doc you can share with content or SEO teams directly from Drive. Works well when the person acting on the gaps lives in Google Docs, not Notion. ```text theme={null} For [brand name] in Scrunch, run a visibility gap analysis. 1. Get all tags. For each tag, pull presence metrics for the last 30 days and calculate the presence rate. 2. Rank tags by presence rate from lowest to highest. Show me the bottom 5. 3. For the lowest-performing tag, list the specific prompts where [brand name] is not present. Sort by observation count. 4. Get citation metrics for that tag — what share is going to competitors vs. third parties vs. brand-owned? 5. Check: which tracked competitor appears most in that tag's gap prompts? Give me a prioritized summary: the top 3 topic areas to focus on, the highest-urgency prompt in each, and one specific content recommendation per area. ``` *** ## Tips Observation count is how many times Scrunch has run that prompt across AI platforms. Higher observation count = more data points. A prompt with a high observation count where you're absent is a reliable gap, not just a one-off miss. Prioritize those. Once the Notion database is created, run the Scrunch-only version monthly and paste the results into the existing database. Ask Claude to "update the existing \[brand name] Visibility Gap Tracker in Notion with this month's data, keeping the same structure." If you want to focus on one part of the funnel, add a filter: "Do this analysis for consideration-stage prompts only" or "Filter to tags that include 'awareness'". You can run this workflow once per funnel stage if needed. *** See who's winning in the gaps you just found — and build a displacement map. Deeper gap analysis prompts including citation-level and platform-specific breakdowns. # GSC Query-Gap Prompt Expansion Source: https://developers.scrunch.com/mcp/workflows/gsc-query-gap-expansion Find Google Search Console queries you already rank for that aren't tracked as Scrunch prompts yet, and bulk-create prompts for the top gaps. If a query already sends you organic traffic, you have a reason to know whether AI assistants answer it the same way search does — but you can't know that if Scrunch isn't tracking it. This workflow finds that blind spot and closes it, expanding prompt coverage based on queries you've already proven matter. **Tools used in this workflow** | Tool | Required? | Used for | | ------------------------- | --------- | ---------------------------------------------------------- | | Scrunch MCP | Required | Checking existing prompt coverage and creating new prompts | | Google Search Console MCP | Required | Sourcing real search queries you already rank for | Looking for content gaps instead of monitoring gaps? Use [Where Search Rankings and AI Presence Diverge](/mcp/workflows/search-vs-ai-gaps) — that workflow finds pages that need new or improved content. This one just makes sure you're watching the right queries in the first place. *** ```text theme={null} For [brand name] / [domain], find search queries we rank for that aren't tracked as Scrunch prompts yet, and create prompts for the highest-value gaps. Step 1 — Pull our real search queries: From Google Search Console, get the top [50] queries by impressions for [domain] over the last 90 days, where we rank in the top 10. Include impressions, clicks, and average position for each. Step 2 — Check existing coverage: List all prompt variants currently tracked for [brand name] in Scrunch. Compare against the Step 1 query list — which of our top-ranking search queries have no closely-matching Scrunch prompt at all? Step 3 — Prioritize the gaps: Of the uncovered queries, rank by impressions — these are the ones worth monitoring first since they represent proven search demand. Step 4 — Create prompts for the top gaps: For the top [10] uncovered queries, create a Scrunch prompt for each, phrased as a natural question rather than the raw keyword string. Tag each one "gsc-expansion" so we can track this batch separately, and assign the appropriate funnel stage based on query intent (informational = awareness, comparison/branded = consideration or decision). Step 5 — Confirm: List everything created, with the original search query, impressions, and the prompt text Claude generated for it. ``` **What you get:** A batch of new Scrunch prompts sourced directly from queries you already know drive real search traffic — so your AI monitoring coverage starts where your proven search demand already is, instead of guessing. *** ## Tips Search queries are often keyword fragments ("best crm small business"), but AI assistants get asked full questions ("what's the best CRM for a small business"). Step 4 asks Claude to rephrase — check a few of the generated prompts to make sure the intent held up in translation. Search rankings and query volume shift over time — re-run this every quarter to catch new queries you've started ranking for since the last pass, rather than treating prompt coverage as a one-time setup task. If \[domain] is large, scope Step 1 to a specific subdirectory or page group (e.g. "queries where the ranking page is under /pricing/") to keep this workflow focused on one part of the business at a time. Give new prompts 30 days to accumulate observations, then run the Rankings & Priority Lists prompts from the Prompt Library — the "gsc-expansion" tag makes it easy to filter to just this batch and see how AI presence compares to the search rank you started from. *** For finding content fixes rather than monitoring gaps. A broader keyword-list version of this same idea, sourced from Semrush/Ahrefs instead of GSC. # Build an AI Content Brief from Keyword Rankings Source: https://developers.scrunch.com/mcp/workflows/keyword-rankings-to-ai-brief Combine Semrush or Ahrefs keyword rankings with Scrunch citation gaps to prioritize which content to create or fix and what it must say to get cited. Keyword tools tell you what people search for. Scrunch tells you what AI engines answer without citing you. Together, they give you the clearest possible picture of where to invest in content: topics with high search volume, proven buyer intent, and a citation gap you can close. **Tools used in this workflow** | Tool | Required? | Used for | | ------------- | ------------------------ | ------------------------------------------- | | Scrunch MCP | Required | Citation gaps and AI presence data by topic | | Semrush MCP | Required for Semrush tab | Keyword rankings, volume, and difficulty | | Ahrefs export | Required for Ahrefs tab | Keyword rankings — paste a CSV export | Choose your keyword tool in the tabs below. Don't have either? Use the [SEO Keywords to Prompts](/mcp/workflows/prompts-from-keywords) workflow instead, which works with any pasted keyword list. *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name], use Semrush keyword data and Scrunch citation data together to build a prioritized AI content brief. Step 1 — Pull top-ranking keywords from Semrush: Get the top [50] organic keywords for [domain] ranked in positions 1–20. Show me: keyword, position, monthly search volume, keyword difficulty, and the URL that's ranking. Step 2 — Pull Scrunch citation gaps: In Scrunch for [brand name], get all tags and calculate the citation rate from [brand domain] for each — variants with brand_present = true and citation pointing to [brand domain] divided by total variants. Rank by citation rate from lowest to highest. Also pull presence metrics for the last 30 days. Step 3 — Find where SEO authority and AI presence diverge: Semantically match each Semrush keyword to the closest Scrunch tag. Identify: - Keywords in positions 1–10 with high search volume but AI citation rate under [30]% - Keywords where Semrush shows a strong ranking URL but Scrunch shows competitors winning the AI citations for that topic - Keywords with high volume but no corresponding Scrunch tag (a tracking gap worth fixing) Rank these by opportunity: (monthly search volume × keyword difficulty score) ÷ AI citation rate. Higher = more valuable to fix. Step 4 — Build the AI content brief: For the top 3 gap opportunities, write a content brief for each: - The keyword, search volume, and keyword difficulty - The Scrunch prompts in this topic where brand is absent (most-observed first) - What competing content or third-party sources are winning the AI citations - Recommended content format and angle to win both the search result and the AI citation - Specific facts, data points, or claim structures that would make this content more citable than what's currently appearing ``` **What you get:** Three ready-to-act content briefs, each grounded in both keyword volume data and AI citation gaps. These are the highest-priority pieces to create or rewrite — backed by two independent data sources pointing at the same opportunity. Export your keyword rankings from Ahrefs (Site Explorer → Organic Keywords → Export) and paste the data below. ```text theme={null} I'm going to paste Ahrefs keyword ranking data for [domain] below. Use it alongside Scrunch to build a prioritized AI content brief. Here's my Ahrefs organic keywords data: [Paste your keyword, position, volume, and keyword difficulty columns here] For [brand name] in Scrunch, get all tags and calculate the citation rate from [brand domain] for each tag. Rank by citation rate from lowest to highest. Also pull presence metrics for the last 30 days. Cross-reference the Ahrefs keywords against the Scrunch tags — semantically match each keyword to the closest tag. Find: - Keywords in positions 1–10 with meaningful search volume but AI citation rate under 30% - Keywords where the ranking URL has authority but Scrunch shows competitors winning the AI citations for that topic - High-volume keywords with no corresponding Scrunch tag (worth adding as a tracking prompt) Rank by opportunity: highest volume × lowest AI citation rate = most urgent. For the top 3 gap opportunities, write a content brief for each: - Keyword, search volume, and keyword difficulty - The Scrunch prompts in this topic where brand is absent (most-observed first) - What's winning the AI citations instead - Recommended content format and the specific angle that would out-answer what's currently cited - Facts, data points, or claim structures that would make this content more extractable by AI ``` **What you get:** Three ready-to-act content briefs grounded in both your Ahrefs ranking data and Scrunch citation gaps — the highest-priority pieces to create or rewrite. *** ## Tips Keyword tools optimize for search engines. Scrunch optimizes for AI engines. A keyword with high volume and a strong ranking page is a proven topic — but if AI isn't citing your page for it, you're getting the search traffic without the AI influence. Combining the two surfaces the topics where a single content improvement wins on both channels simultaneously. This means your AI tracking coverage has gaps. After running this workflow, add the high-volume keywords as new Scrunch prompts using the SEO Keywords to Prompts workflow — then you'll have data on them for next time. Pass them directly into the Create Content for AI Citations workflow — that workflow accepts a brief as input in Step 2 and can publish through your CMS in the same conversation. This workflow is most useful at the start of a quarterly content planning cycle. Run it once, get the 3–5 highest-priority briefs, and use those to anchor your sprint. Revisit after the content publishes using the Measure AI Visibility's Impact on Traffic workflow to see what moved. *** Take the content briefs from this workflow and generate the actual content, then publish through your CMS. After publishing, use this workflow to measure whether improving AI presence drove traffic growth. # Which Cited Pages Actually Convert Source: https://developers.scrunch.com/mcp/workflows/landing-page-citation-impact Cross-reference the specific pages AI engines are citing against Google Analytics conversion data to see which citations are driving more than just traffic. Getting cited is the goal, but not every citation is worth the same. This workflow checks the pages Scrunch shows are being cited against what Google Analytics shows those same pages actually do once someone lands on them — traffic, sure, but also whether they convert. **Tools used in this workflow** | Tool | Required? | Used for | | -------------------- | --------- | ------------------------------------------------------------------ | | Scrunch MCP | Required | Identifying which owned pages are being cited by AI, and how often | | Google Analytics MCP | Required | Traffic and conversion data for those specific pages | Looking for the broader before/after presence-vs-traffic story instead of a per-page breakdown? Use [Measure AI Visibility's Impact on Traffic](/mcp/workflows/ai-visibility-traffic-impact) — this workflow is the page-level follow-up once you know visibility is trending up. *** ```text theme={null} For [brand name] in Scrunch, find which of our AI-cited pages are also converting well, and which are getting cited but going nowhere. Step 1 — Find the cited pages: Pull prompt variants filtered to citation_domain = [brand domain]. Sort by observation count. Take the top 15 — these are the specific owned URLs getting cited most, along with which prompts and platforms cite them. Step 2 — Pull the traffic and conversion data: For each of those URLs, get from Google Analytics over the last [30/90] days: - Sessions and users (landing page traffic) - Conversion rate on [your primary conversion event — e.g. form submit, signup, demo request] - Bounce rate Step 3 — Rank the pages into three buckets: - **Working as intended**: high citation count, healthy traffic, and converting at or above site average - **Traffic without conversion**: high citation count and traffic, but converting below average — the page is being found but not closing - **Cited but quiet**: high citation count but low traffic — citations aren't translating into visits yet, worth checking if the cited URL is even the ideal landing experience Step 4 — Recommend action: For "traffic without conversion" pages, what's the likely fix — unclear CTA, mismatched intent, missing trust signals? For "cited but quiet" pages, is this expected (top-of-funnel content) or a sign something's blocking click-through? ``` **What you get:** A page-level view of which citations are actually earning their keep — separating the pages worth protecting and replicating from the ones that need a conversion-focused fix, not more visibility. *** ## Tips Be specific in Step 2 about what "conversion" means for your business — a newsletter signup and a demo request are very different bars. If you track multiple conversion events, run this once per event to see if a page performs differently depending on the goal. Citations for awareness-stage, educational content are often "cited but quiet" by design — a comparison page or a glossary entry gets referenced by AI far more than clicked directly. Check the prompt's funnel stage from Step 1 before treating this as a fix-it item. "Traffic without conversion" pages are strong candidates for the Create Content That Gets AI Citations workflow's optimization path — the citation and traffic are already working, so a conversion-focused rewrite has a clear existing audience to improve. If you have many cited pages, group Step 1's results by tag or topic instead of listing pages individually — you'll get a cleaner signal on which topic areas convert well versus which just generate visibility. *** Start here for the broader before/after visibility-to-traffic story. Use these findings to prioritize which cited pages need a conversion-focused rewrite. # Monthly Client Report, Built Automatically Source: https://developers.scrunch.com/mcp/workflows/monthly-client-report Pull a month's worth of visibility data and have Claude write, structure, and save a complete report to Notion — ready to share or drop into a deck. One prompt. Full monthly report. Paste it in at the end of each month and get a structured Notion page with all the analysis, competitive data, and recommendations written for you. **Tools used in this workflow** | Tool | Required? | Used for | | -------------------- | --------- | --------------------------------------------------------- | | Scrunch MCP | Required | All visibility, competitive, sentiment, and citation data | | Notion MCP | Optional | Saving the report as a shareable Notion page | | Google Workspace MCP | Optional | Saving the report as a Google Doc | *** ```text theme={null} For [brand name] in Scrunch, build the complete AI visibility report for [month year]. Step 1 — Pull all performance data: 1. Overall presence rate for the last 30 days 2. Platform breakdown: presence rate per AI platform, ranked best to worst 3. Sentiment for the last 30 days: breakdown of positive, neutral, and negative 4. Citation health: split of brand-owned vs. competitor vs. third-party citations 5. Share of voice: presence rates for [brand name] and all tracked competitors, ranked 6. Top 5 topic areas by presence rate — where we're strongest 7. Bottom 5 topic areas by presence rate — where we're weakest Step 2 — Write the report in Notion: Create a Notion page titled "[Month Year] AI Visibility Report — [brand name]" and structure it exactly like this: ## Executive Summary Two to three sentences: overall visibility health, the single biggest win this month, and the top priority for next month. ## Visibility Performance Platform breakdown table. One sentence on the strongest platform and one on the weakest. ## Competitive Position Share of voice ranking table. Note any competitor that moved significantly. One sentence on our overall competitive standing. ## Content Health Top 5 performing topics (these are working — protect them). Bottom 5 underperforming topics (these need attention). One sentence on citation health. ## Recommendations for Next Month Three specific actions. For each: what to do, which data point justifies it, and what success looks like. Format everything for direct copy-paste into a slide deck — use tables, headers, and bullet points throughout. No dense paragraphs. ``` **What you get:** A complete Notion report that's immediately shareable with a client or leadership team, and structured cleanly enough to paste into Google Slides or a PowerPoint. The recommendations section is actionable, not generic — Claude ties each one to a specific number from the data. ```text theme={null} For [brand name] in Scrunch, build the complete AI visibility report for [month year]. Step 1 — Pull all performance data: 1. Overall presence rate for the last 30 days 2. Platform breakdown: presence rate per AI platform, ranked best to worst 3. Sentiment for the last 30 days: breakdown of positive, neutral, and negative 4. Citation health: split of brand-owned vs. competitor vs. third-party citations 5. Share of voice: presence rates for [brand name] and all tracked competitors, ranked 6. Top 5 topic areas by presence rate — where we're strongest 7. Bottom 5 topic areas by presence rate — where we're weakest Step 2 — Write the report as a Google Doc: Create a new Google Doc titled "[Month Year] AI Visibility Report — [brand name]" in [folder name or Drive location] and structure it exactly like this: ## Executive Summary Two to three sentences: overall visibility health, the single biggest win this month, and the top priority for next month. ## Visibility Performance Platform breakdown table. One sentence on the strongest platform and one on the weakest. ## Competitive Position Share of voice ranking table. Note any competitor that moved significantly. One sentence on our overall competitive standing. ## Content Health Top 5 performing topics (these are working — protect them). Bottom 5 underperforming topics (these need attention). One sentence on citation health. ## Recommendations for Next Month Three specific actions. For each: what to do, which data point justifies it, and what success looks like. Format everything for direct copy-paste into a slide deck — use tables, headers, and bullet points throughout. No dense paragraphs. ``` **What you get:** A complete Google Doc report ready to share via Drive link or drop into Google Slides. Works well for teams that collaborate in comments and suggestions directly in Docs. ```text theme={null} For [brand name] in Scrunch, build the AI visibility report for [month year]. Pull: 1. Overall presence rate for the last 30 days 2. Platform breakdown: presence rate per platform, ranked 3. Sentiment: breakdown of positive, neutral, negative 4. Citation health: brand-owned vs. competitor vs. third-party 5. Competitive share of voice: all tracked competitors ranked by presence rate 6. Top 5 tags by presence rate 7. Bottom 5 tags by presence rate Structure the output as a complete report with these sections: Executive Summary, Visibility Performance, Competitive Position, Content Health, Recommendations for Next Month. Write recommendations as specific actions tied to specific numbers — not generic advice. ``` *** ## Tips Run the full prompt for each brand back-to-back in the same Claude conversation. Claude creates a separate Notion page for each brand. At the end, ask it to "create a summary page in Notion that links to all the individual brand reports from this session" for an agency-style index. Add this line to Step 1: "Also pull presence metrics for the 30 days before that period so we can show month-over-month trend direction." Claude will then include a comparison column in the platform table and flag meaningful changes. If you're dropping this into a presentation, add to the Notion step: "Write each section heading as a slide title, keep each bullet to one line maximum, and bold the key number in each bullet." This makes the Notion page paste cleanly into a deck without reformatting. *** Keep stakeholders updated week-to-week between monthly reports. Run this first to have competitive context ready for the report. # New Brand Live in One Conversation Source: https://developers.scrunch.com/mcp/workflows/new-brand-live MCP workflow that onboards a brand end to end: creates the brand, adds competitors, and seeds a tagged prompt library from one chat with your AI agent. Paste this in when onboarding a new brand or client. Your AI agent creates everything in Scrunch directly — the brand, competitors, and an initial prompt library tagged by funnel stage — then confirms the setup when it's done. **Tools used in this workflow** | Tool | Required? | Notes | | ----------- | --------- | --------------------------------------------------------------------------------- | | Scrunch MCP | Required | Editor or Admin-level permissions on a Scrunch Agency or Enterprise plan required | This workflow uses write operations. Your AI agent will confirm before creating anything — you'll see each step as it runs. *** ```text theme={null} I need to configure a new brand in Scrunch. Let's do the full setup in this conversation. Step 1 — Create the brand: Create a new brand with: - Name: [brand name] - Website: [website.com] - Description: [one or two sentences describing what the brand does and who it serves] Confirm it was created and give me the brand ID. Step 2 — Add competitors: Add these competitors to [brand name]: - [Competitor 1], website: [competitor1.com] - [Competitor 2], website: [competitor2.com] - [Competitor 3], website: [competitor3.com] Confirm all competitors were added. Step 3 — Create awareness-stage prompts: Create 5 prompts for [brand name] that a potential customer would type into an AI assistant at the very top of the funnel — when they're looking for a solution in [category] but don't know [brand name] yet. Write them as natural questions, not keyword strings. Tag each prompt as "awareness". Step 4 — Create consideration and decision prompts: Create 3 consideration-stage prompts (someone actively comparing options in [category]) and 2 decision-stage prompts (someone ready to choose, looking for final confirmation). Tag the consideration prompts as "consideration" and the decision prompts as "decision". Step 5 — Confirm the setup: List everything we just created: brand details, full competitor list, and all prompts grouped by tag. I want to confirm it looks right before data starts collecting. ``` **What you get:** A fully configured Scrunch brand ready to start collecting data. Expect first metrics within 24–48 hours as prompts begin running. After 30 days you'll have enough data to run the [visibility gap analysis](/mcp/workflows/find-visibility-gaps) and [competitive SOV report](/mcp/workflows/competitor-share-of-voice). *** ## Tips The more specific your brand description in Step 1, the better the generated prompts in Steps 3–4. Include: the product category, the primary audience, and the key problem the brand solves. For example: "B2B SaaS for mid-market HR teams to automate onboarding workflows." Once the brand is live, use the Prompt Gap Analysis prompt from the [Prompt Library](/mcp/prompts/visibility-gaps) to expand coverage systematically. It's designed to build on an initial library rather than start from scratch. Run the full prompt once per brand in the same conversation. Start each with: "Now let's set up \[brand 2 name]. Same process as before." Your AI agent keeps each brand's configuration separate. *** Once 30 days of data are in, run this to see where to focus content investment. Configuration and tag management prompts to keep your setup clean over time. # Build Your Prompt Library from SEO Keywords Source: https://developers.scrunch.com/mcp/workflows/prompts-from-keywords Compare your SEO keyword list against existing Scrunch prompts, cluster the gaps, and create new tracking prompts in one conversation. Your SEO keyword research already tells you what buyers search for. This workflow maps those keywords against your current Scrunch prompt coverage, finds the gaps, converts them into natural-language AI queries, and adds them to Scrunch — so your AI visibility tracking matches your SEO strategy. **Tools used in this workflow** | Tool | Required? | Used for | | ------------------------------- | --------- | ----------------------------------------------- | | Scrunch MCP | Required | Listing existing prompts, creating new ones | | Keyword data | Required | Paste from any source — see input options below | | Google Search Console MCP | Optional | Pull queries directly without exporting | | Ahrefs / SEMrush / Keyword tool | Optional | Paste a CSV export into the prompt | *** ## Keyword input options You don't need a specific tool connected. Claude can work with keyword data in any of these forms: Copy your keywords from any tool (Ahrefs, SEMrush, Keyword Planner, Clearscope, etc.) and paste them directly into the prompt in Step 2. ```text theme={null} Here are the keywords to analyze: best project management software project management tools for remote teams asana vs monday.com how to manage remote team tasks ... ``` If you have Google Search Console connected as an MCP, replace Step 2 with: ```text theme={null} Pull the top 100 queries by impressions from Google Search Console for [domain] over the last 90 days. Filter to queries with more than 50 impressions. Use those as the keyword input for the gap analysis. ``` Export a keyword report from Ahrefs, SEMrush, or Moz as CSV. Paste the contents or upload the file and reference it in Step 2: ```text theme={null} I've attached a keyword export from [tool name]. Use the "Keyword" column as the input for the gap analysis. Ignore any keywords with fewer than [X] monthly searches. ``` *** ## The workflow ```text theme={null} List all active prompt variants for [brand name] in Scrunch. I want to see the full seed prompt text for each one so I can map it against keyword data. ``` ```text theme={null} Here is a list of SEO keywords and questions we're targeting for [brand name]: [paste your keyword list here] Compare these against the Scrunch prompts you just pulled. Classify each keyword into one of three buckets: 1. Already covered — there's an existing Scrunch prompt that tracks this topic or a close equivalent 2. Partially covered — we're tracking the general topic but missing this specific angle or intent 3. Not covered — no existing prompt comes close to this keyword Show me the "partially covered" and "not covered" keywords — those are the gaps. ``` ```text theme={null} Take the gap keywords from the previous step and: 1. Group them into topic clusters — keywords that are semantically related and could be addressed by similar content 2. For each cluster, write 2–4 natural-language questions that a user would actually type into an AI assistant to get information on this topic. These should sound like real questions, not keyword strings. 3. For each prompt, note whether the intent is awareness (general research), consideration (comparing options), or decision (ready to choose) Show me the clusters and proposed prompts before creating anything — I want to review them first. ``` Once you've reviewed the proposed prompts: ```text theme={null} Create the following new prompts for [brand name] in Scrunch. Tag each with its funnel stage (awareness / consideration / decision) and also add the tag "[seo-import]" so I can track this batch separately. [list the prompts you approved in the previous step] ``` ```text theme={null} List all prompts for [brand name] tagged "[seo-import]" to confirm they were created correctly. How many prompts did we add? What's the breakdown by funnel stage? ``` *** ## Tips Claude handles up to a few hundred keywords in a single prompt well. For larger keyword sets (1,000+), run the analysis in batches by topic cluster or funnel stage — it produces cleaner output and avoids truncation. After the clustering step, ask: "Rank these gap clusters by commercial relevance for \[brand name] — which topics represent the highest-value buyers if we appear in AI responses for them?" This focuses your new prompts on business impact, not just coverage volume. SEO keyword priorities shift. Run this workflow every quarter with a fresh export. Use the `[seo-import-q[quarter]-[year]]` tag convention so you can track each batch's performance separately and see which keyword-sourced prompts improve your visibility over time. SEO keywords are often short ("project management software") while effective AI prompts are full questions ("What's the best project management software for a team of 20?"). Claude handles this conversion in Step 3, but you can adjust the output by adding: "Make the prompts more specific — include use-case context, team size, or industry where it makes the question more realistic." *** Once you've added the prompts, use this workflow to create the content that fills those gaps. Find gaps from the Scrunch data side — which prompt categories already have the lowest visibility. # Auto-Build a QBR Deck Source: https://developers.scrunch.com/mcp/workflows/qbr-deck-builder Turn a brand's presence, position, sentiment, and citation metrics into a formatted quarterly business review deck in Google Slides or PowerPoint. Building a QBR deck usually means pulling numbers into a doc, then rebuilding them as slides by hand. This workflow skips the middle step: Claude pulls the quarter's metrics from Scrunch and writes the deck directly, slide by slide, in the presentation tool you already use. **Tools used in this workflow** | Tool | Required? | Used for | | ----------------------------------- | --------------------- | ---------------------------------------------------------- | | Scrunch MCP | Required | Quarterly presence, position, sentiment, and citation data | | Google Slides MCP or PowerPoint MCP | Required (choose one) | Creating the deck | *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, build a QBR deck in Google Slides covering [start date] to [end date]. Step 1 — Pull the quarter's data: - Presence metrics for the period, plus the prior period for comparison - Position metrics for the period - Sentiment breakdown for the period - Citation metrics broken down by owner (brand, competitor, third-party) - Share of voice vs. all tracked competitors (see the Competitor Share of Voice workflow if you want the full displacement analysis first) Step 2 — Build the deck: Create a new Google Slides presentation named "[brand name] QBR — [quarter/year]" with these slides: 1. Title slide: brand name, quarter, "AI Visibility Quarterly Review" 2. Executive summary: 3-4 bullet points on the quarter's biggest movements (up or down) 3. Presence trend: this quarter's presence rate vs. last quarter, with the percentage change 4. Position breakdown: how often we appear top/middle/bottom, with a short interpretation 5. Sentiment: positive/mixed/negative split, and whether it shifted from last quarter 6. Citation ownership: brand vs. competitor vs. third-party share, as a simple breakdown 7. Competitive standing: our share-of-voice rank vs. tracked competitors 8. Recommended focus for next quarter: 2-3 specific, prioritized actions based on the weakest number above Use large, readable numbers on each metric slide — this is a review deck, not a written report. One key number and one supporting line per slide where possible. Step 3 — Confirm and share: Once built, give me the link to the deck so I can review it before the meeting. ``` **What you get:** A shareable Google Slides deck with every quarterly number already placed on its own slide, an executive summary up front, and a next-quarter action slide at the end — ready to present with light editing, not built from a blank deck. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, build a QBR deck in PowerPoint covering [start date] to [end date]. Step 1 — Pull the quarter's data: - Presence metrics for the period, plus the prior period for comparison - Position metrics for the period - Sentiment breakdown for the period - Citation metrics broken down by owner (brand, competitor, third-party) - Share of voice vs. all tracked competitors (see the Competitor Share of Voice workflow if you want the full displacement analysis first) Step 2 — Build the deck: Create a new PowerPoint presentation named "[brand name] QBR — [quarter/year]" with these slides: 1. Title slide: brand name, quarter, "AI Visibility Quarterly Review" 2. Executive summary: 3-4 bullet points on the quarter's biggest movements (up or down) 3. Presence trend: this quarter's presence rate vs. last quarter, with the percentage change 4. Position breakdown: how often we appear top/middle/bottom, with a short interpretation 5. Sentiment: positive/mixed/negative split, and whether it shifted from last quarter 6. Citation ownership: brand vs. competitor vs. third-party share, as a simple breakdown 7. Competitive standing: our share-of-voice rank vs. tracked competitors 8. Recommended focus for next quarter: 2-3 specific, prioritized actions based on the weakest number above Use large, readable numbers on each metric slide — this is a review deck, not a written report. One key number and one supporting line per slide where possible. Step 3 — Confirm and save: Once built, confirm the file name and location so I can find it before the meeting. ``` **What you get:** A PowerPoint deck with every quarterly number already placed on its own slide, an executive summary up front, and a next-quarter action slide at the end — ready to present with light editing, not built from a blank deck. *** ## Tips If you'd rather present live, interactive charts instead of static slide images, build an Executive Explorer Dashboard first and drop its link into the deck's appendix — stakeholders who want to dig into a specific metric can click through instead of asking follow-up questions mid-meeting. If you manage several client brands, run Step 1 once per brand and ask Claude to hold each brand's numbers in memory before moving to Step 2 — then build all the decks in the same conversation rather than starting over each time. Not every quarter has a dramatic story. If presence, position, and sentiment are all roughly flat, say so directly in the executive summary rather than manufacturing urgency — "stable performance, no action needed" is a legitimate and often reassuring slide. Duplicate the deck at the start of the next quarter and ask Claude to replace only the metric slides (3-7) with fresh data, keeping the same structure. This keeps the deck format consistent for stakeholders who see it every quarter. *** Build a live, clickable companion dashboard to link from the deck's appendix. For a written report between QBRs, use this instead — same data, different format. # Where Search Rankings and AI Presence Diverge Source: https://developers.scrunch.com/mcp/workflows/search-vs-ai-gaps MCP workflow that joins Google Search Console queries with Scrunch data to find pages ranking in search but missing from AI responses, your top-ROI fixes. Ranking well in Google and being cited by AI are two different things. This workflow finds the gap between them: queries where you're on page one in search but absent from AI responses. Those are your highest-value content fixes — the authority is already there, the AI just isn't picking you up yet. **Tools used in this workflow** | Tool | Required? | Used for | | ------------------------- | ----------- | -------------------------------------------------------- | | Scrunch MCP | Required | AI presence and citation data by topic | | Google Search Console MCP | Recommended | Pulling your top search queries directly | | GSC export | Alternative | Paste a CSV from GSC if you don't have the MCP connected | Choose your input method in the tabs below. *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name], find the queries where we rank well in Google Search but AI engines aren't citing our content. Step 1 — Pull search queries from Google Search Console: Get the top 100 queries for [domain] over the last 90 days, filtered to queries with more than [50] impressions. Show me: query text, impressions, clicks, and average position. Step 2 — Pull AI visibility data from Scrunch: In Scrunch for [brand name], get all tags and pull presence metrics for the last 30 days. For each tag, calculate the presence rate and the citation rate to [brand domain]. Step 3 — Cross-reference and find the gaps: Semantically match each GSC query to the most relevant Scrunch tag. Then identify the queries where: - You have significant search impressions at position 1–10 in Google, but AI presence is under [30]% - You're receiving search traffic but AI engines are citing competitors or third parties instead Rank by opportunity: highest impressions × lowest AI presence rate = most urgent. Step 4 — Summarize the priority list: Give me a ranked list of the top [5–10] opportunities. For each: the query, search impressions, Google position, current AI presence rate, and what source AI is citing instead of us. ``` **What you get:** A ranked list of content gaps where your existing search authority isn't translating into AI citations. These are the highest-ROI fixes — you don't need to build authority from scratch, you need to restructure content so AI can extract and cite it. Export from Google Search Console (Performance → Queries → Export) and paste the data directly. ```text theme={null} I'm going to paste my Google Search Console query data below. Use it alongside Scrunch to find where I rank well in search but AI doesn't cite my content. Here's my GSC data for [domain] over the last 90 days: [Paste your query, impressions, clicks, and position columns here] For [brand name] in Scrunch, get all tags and pull presence metrics for the last 30 days. Calculate the citation rate to [brand domain] for each tag. Cross-reference the search queries above against the Scrunch tags — semantically match each query to the closest tag. Find the queries where: - I have meaningful impressions at position 1–10 but AI presence is under 30% - Competitors or third parties are getting the AI citations instead Rank the top [5–10] opportunities by: highest impressions × lowest AI presence rate. For each, show: the query, impressions, Google position, AI presence rate, and who's winning the AI citation. ``` **What you get:** The same ranked gap list, built from data you pasted rather than a live connection. Works with any GSC export — just include the query, impressions, and position columns. No GSC data? This version identifies the same type of gap using Scrunch's own data — it just can't cross-reference against actual search positions. ```text theme={null} For [brand name] in Scrunch, find the topic areas where there's strong evidence that content exists and ranks but AI isn't citing it. 1. Get all tags and pull presence metrics for the last 30 days. Rank by presence rate lowest to highest. 2. For the 5 lowest-performing tags, get citation metrics: what share of citations are going to competitors vs. third parties vs. brand-owned? 3. For the same tags, list the specific prompts where brand_present = false with the highest observation counts — these are the most-asked questions where we're absent. 4. Check: are there tags where we have some AI presence (10–30%) but it's inconsistent? Those are likely pages that exist but aren't structured for AI citation. Give me a prioritized list of the biggest content gaps with a one-line recommendation for each: new content needed, or existing content needs restructuring. ``` *** ## Tips Google ranks pages on domain authority, backlinks, and keyword optimization. AI engines cite pages based on how directly and clearly they answer a question — factual specificity, structure, and extractability matter more than authority signals. A page can rank #1 in Google and still never be cited by AI if it's written in a promotional rather than informational style. Don't create new pages for queries where you already rank. Instead, use the Create Content for AI Citations workflow to restructure existing pages: add a direct answer at the top, rewrite factual sections to be more specific, and reframe headings to match how questions are asked in AI prompts. The goal is to make your existing content more extractable, not replace it. Run it quarterly — GSC impressions shift as search trends change, and your Scrunch presence improves as you fix content. Each run will surface new gaps and let you retire ones you've already closed. Add this to Step 3: "Filter to queries that indicate commercial intent — comparisons, 'best X', 'how to choose X', or branded competitor queries. Exclude navigational queries like '\[brand] login' or '\[brand] pricing'." This keeps the gap list focused on queries where AI citations actually influence buying decisions. *** Once you have the gap list, use this workflow to restructure or create the content that fills it. Turn the queries from this analysis into Scrunch tracking prompts so you can monitor improvement over time. # Draft a Stakeholder Email Update Source: https://developers.scrunch.com/mcp/workflows/stakeholder-email-update Pull this period's AI visibility headlines from Scrunch and have Claude draft a stakeholder email update, staged for your review before sending. Not every update needs a full report or a meeting — sometimes a client or exec just needs three sentences and a number. This workflow pulls the headline metrics and drafts the email for you. It always stops at a draft: you read it, edit it, and send it yourself. **Tools used in this workflow** | Tool | Required? | Used for | | ------------------------ | --------------------- | -------------------------------------- | | Scrunch MCP | Required | Pulling this period's headline metrics | | Gmail MCP or Outlook MCP | Required (choose one) | Creating the draft in your inbox | This workflow only creates a draft — it will not send anything. Review it in your inbox before hitting send. *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, draft a short stakeholder update email in Gmail. Step 1 — Pull the headlines: Get presence, position, sentiment, and citation metrics for the last [7/30] days, compared to the prior period. Identify the single biggest positive movement and, if there is one, the single biggest area of concern. Step 2 — Draft the email: Create a Gmail draft: To: [recipient email] Subject: [brand name] AI Visibility Update — [date] Body (keep it under 150 words, no more than 2 short paragraphs): - Open with the headline number and its change (e.g. "Our AI visibility rose X points this [week/month], driven by...") - One sentence on what's driving the change - One sentence flagging anything that needs attention, if applicable - Close with one sentence on what happens next (nothing needed / a recommended action / a heads-up about an upcoming report) Sign off as [your name]. Step 3 — Confirm: Tell me the draft is ready and summarize what it says so I can review it before sending. ``` **What you get:** A Gmail draft sitting in your drafts folder, written and ready — you review, tweak the tone if needed, and send. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, draft a short stakeholder update email in Outlook. Step 1 — Pull the headlines: Get presence, position, sentiment, and citation metrics for the last [7/30] days, compared to the prior period. Identify the single biggest positive movement and, if there is one, the single biggest area of concern. Step 2 — Draft the email: Create an Outlook draft: To: [recipient email] Subject: [brand name] AI Visibility Update — [date] Body (keep it under 150 words, no more than 2 short paragraphs): - Open with the headline number and its change (e.g. "Our AI visibility rose X points this [week/month], driven by...") - One sentence on what's driving the change - One sentence flagging anything that needs attention, if applicable - Close with one sentence on what happens next (nothing needed / a recommended action / a heads-up about an upcoming report) Sign off as [your name]. Step 3 — Confirm: Tell me the draft is ready and summarize what it says so I can review it before sending. ``` **What you get:** An Outlook draft sitting in your drafts folder, written and ready — you review, tweak the tone if needed, and send. *** ## Tips The 150-word limit in Step 2 is deliberate — this workflow is for the update that doesn't warrant a deck or a report, just a quick, confident status check. If you find yourself wanting to add more, that's usually a sign you want the Weekly AI Brief or Monthly Client Report workflow instead. If nothing moved meaningfully, say so directly in Step 2 rather than manufacturing a headline: "Visibility held steady this period — no action needed." A short, honest "all clear" email builds more trust than an overstated one. Run Step 2 once per recipient if different stakeholders need different framing (e.g. a client needs the polished version, an internal teammate needs the raw numbers). Ask Claude to create a separate draft for each rather than trying to write one email that serves both audiences. Sending email on your behalf is treated as an action that needs your explicit review every time, not a one-time approval — so this workflow is intentionally designed to hand you a draft rather than send automatically, even if you run it the same way every week. *** For a fuller weekly update with more context than a short email allows. For internal team visibility instead of a stakeholder-facing email. # Switch from Another AI Visibility Tool in One Conversation Source: https://developers.scrunch.com/mcp/workflows/switch-from-another-tool MCP workflow to migrate brands, personas, tags, competitors, and your full prompt library from another AI visibility tool into Scrunch in one chat. Switching from another AI visibility tool? You don't have to rebuild your setup by hand. Run one prompt in your current tool to export everything — brands, personas, tags, alternative names, competitors, and your full prompt library — then paste the result into a Scrunch MCP chat and have your AI agent recreate it all directly. **Tools used in this workflow** | Tool | Required? | Notes | | --------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- | | Scrunch MCP | Required | Editor or Admin-level permissions on a Scrunch Agency or Enterprise plan required | | Your current tool's MCP, CSV export, or settings UI | Required | Any source where your existing configuration is visible — MCP-connected chat, downloaded CSVs, or text copied from a settings page | Step 2 uses write operations in Scrunch. Your AI agent will confirm before creating anything — you'll see each step as it runs. *** ## Step 1 — Export your setup Pick the path that matches the tool you're moving off of. Open a chat with the AI assistant that's connected to your current tool's MCP server (or its API), and paste this prompt. It returns a structured, copy-paste-ready dump of your entire configuration. ```text theme={null} Export everything you can read about my AI visibility configuration from the tool you're connected to. Preserve my exact wording where possible — especially for prompt text, brand descriptions, alternative names, and persona definitions. ## Categories (output in this order): 1. **Brands** — One entry per tracked brand. For each, include: name, primary website/domain, one or two sentence description, alternative names / aliases / variants, and any unique identifier the tool stores. 2. **Personas** — Audience personas defined for each brand. Verbatim names and descriptions. Note which brand each persona belongs to. 3. **Tags / Topics** — Every tag or topic label used to categorize prompts. Include the label and a one-line meaning if available. Note whether tags are global or scoped to a specific brand. 4. **Competitors** — One entry per competitor, grouped under the brand it's tracked for. Include competitor name and website/domain. 5. **Prompts** — One entry per tracked prompt. For each, include: the brand it belongs to, the prompt text verbatim, any persona it's assigned to, and any tags applied. ## Format: Use a section header for each category. Within each category, list one entry per line. Format brand and prompt lines so they're machine-readable: - Brand: ` | website: | aliases: | description: ` - Persona: ` | persona: | description: ` - Tag: ` | meaning: | scope: ` - Competitor: ` | competitor: | website: ` - Prompt: ` | persona: | tags: | prompt: ` Preserve original wording. Do not paraphrase prompt text, descriptions, or persona definitions. ## Output: - Wrap the entire export in a single fenced code block for easy copying. - After the code block, state whether this is the complete set or whether any category was truncated. If truncated, say which category and roughly how many entries remain. ``` Save the resulting code block — you'll paste it into Scrunch in Step 2. Download every CSV your current tool offers — usually one for brands, one for prompts, one for competitors, and sometimes a tags or personas export. Then open a fresh chat with any capable AI assistant (Claude, ChatGPT, etc.), paste **all** the CSV contents in one after another, and use this prompt to reformat them. ```text theme={null} I've pasted CSV exports from my AI visibility tool below. Reformat them into a single, structured export I can hand to another tool's AI agent. Preserve my exact wording where possible — especially for prompt text, brand descriptions, alternative names, and persona definitions. ## Categories (output in this order): 1. **Brands** — One entry per brand: name, primary website/domain, description, alternative names / aliases, identifier. 2. **Personas** — Audience personas per brand, verbatim names and descriptions. 3. **Tags / Topics** — Every tag or topic label, with a one-line meaning if present in the CSVs. 4. **Competitors** — One entry per competitor, grouped under its brand. 5. **Prompts** — One entry per prompt, with brand, persona (if any), tags (if any), and the prompt text verbatim. ## Format: Section header per category, one entry per line. Use these line shapes: - Brand: ` | website: | aliases: | description: ` - Persona: ` | persona: | description: ` - Tag: ` | meaning: | scope: ` - Competitor: ` | competitor: | website: ` - Prompt: ` | persona: | tags: | prompt: ` Do not paraphrase prompt text, descriptions, or persona definitions. ## Output: - Wrap the entire export in a single fenced code block. - After the code block, note any fields that were missing from the CSVs (e.g., "no personas column was present"). --- CSV content begins below --- [paste all CSV contents here] ``` If your current tool has no MCP, no API, and no CSV export, copy whatever text you can pull from the settings or configuration screens — brand names, prompt lists, persona blurbs, competitor lists, tag labels. Paste it all into a fresh chat with any capable AI assistant and use this prompt to normalize it. ```text theme={null} I've pasted raw text copied from the settings of my AI visibility tool below. The structure is inconsistent — some sections are tables, some are lists, some are paragraphs. Normalize it into a single, structured export. Preserve my exact wording where possible — especially for prompt text, brand descriptions, alternative names, and persona definitions. ## Categories (output in this order): 1. **Brands** — name, primary website/domain, description, alternative names / aliases. 2. **Personas** — per brand, verbatim names and descriptions. 3. **Tags / Topics** — every tag label, with a one-line meaning if present. 4. **Competitors** — per brand, name and website. 5. **Prompts** — per brand, with persona (if any), tags (if any), and verbatim prompt text. ## Format: Section header per category, one entry per line: - Brand: ` | website: | aliases: | description: ` - Persona: ` | persona: | description: ` - Tag: ` | meaning: | scope: ` - Competitor: ` | competitor: | website: ` - Prompt: ` | persona: | tags: | prompt: ` If a field isn't present in the source text, write `unknown` rather than guessing. Do not paraphrase prompt text or descriptions. ## Output: - Wrap the entire export in a single fenced code block. - After the code block, list anything you couldn't confidently place into a category. --- pasted text begins below --- [paste raw text here] ``` *** ## Step 2 — Import into Scrunch Open a fresh chat with an AI assistant connected to the Scrunch MCP. Paste the export from Step 1, then paste this prompt directly after it. ```text theme={null} The block above is an export of my AI visibility setup from another tool. Recreate it in Scrunch. Confirm with me after each step before moving on. Step 1 — Parse and confirm: Read the export and tell me: - How many brands you found - How many personas, tags, competitors, and prompts you found - Anything that looks ambiguous, duplicated, or incomplete Wait for me to confirm before writing anything. Step 2 — Create the brands: Create each brand in Scrunch with its name, website, description, and alternative names from the export. After all brands are created, list them back with their new Scrunch brand IDs. Step 3 — Configure personas and tags: For each brand, set up the personas listed in the export. Then create the tags from the export — global tags first, then brand-scoped tags. Confirm when done. Step 4 — Add competitors: For each brand, add the competitors listed in the export with their websites. Confirm the full competitor count per brand when done. Step 5 — Create the prompt library: For each brand, create every prompt from the export. Apply the persona and tags exactly as listed. Use the prompt text verbatim — do not rewrite or paraphrase. Confirm the prompt count per brand when done. Step 6 — Final summary: List everything you created: brands (with IDs), personas per brand, tags, competitors per brand, and prompts per brand grouped by tag. Flag anything you skipped or couldn't import and explain why. ``` **What you get:** A Scrunch organization that mirrors your previous setup — same brands, same personas, same tags, same competitors, same prompts. First metrics begin landing within 24–48 hours as the prompt library starts running. After 30 days you'll have enough data to compare against your old tool side by side. *** ## Tips MCP tool results are typically capped, and very large prompt libraries can spill past the limit. Re-run the Step 1 prompt once per category — "export only brands and personas", then "export only prompts for brand X" — and import the chunks in sequence. Scrunch's import prompt is happy to pick up where it left off if you tell it which brands are already created. Tag conventions differ across tools. Before Step 5, tell the Scrunch agent how to normalize: e.g., "Map any tag that means top-of-funnel to 'awareness', any comparison tag to 'consideration', and any purchase-intent tag to 'decision'." The agent will apply the mapping consistently across every prompt. Run Step 1 once per workspace in your old tool. Keep each export separate. Then run Step 2 once per export in its own Scrunch chat so the agent doesn't cross-wire competitors or tags between unrelated brands. After Step 6, ask Scrunch: "List every prompt grouped by brand and tag, with persona where assigned." Diff that against your Step 1 export. Anything missing is usually a tag mapping the agent skipped — point it out and ask the agent to backfill. *** Setting up an additional brand from scratch after the migration is done. Once 30 days of data are in, find where your migrated setup is winning and where it's not. # Weekly AI Brief, Saved to Notion or Google Docs Source: https://developers.scrunch.com/mcp/workflows/weekly-ai-brief One prompt pulls this week's visibility data, saves a full brief to Notion or Google Docs, and posts the headline numbers to Slack. Paste this into any Claude conversation with Scrunch connected. With Notion and Slack also connected, Claude handles the full workflow — no exports, no copy-pasting between tabs. **Tools used in this workflow** | Tool | Required? | Used for | | -------------------- | --------- | -------------------------------------------------- | | Scrunch MCP | Required | Pulling visibility, sentiment, and competitor data | | Notion MCP | Optional | Saving the full brief as a Notion page | | Google Workspace MCP | Optional | Saving the full brief as a Google Doc | | Slack MCP | Optional | Posting the summary to a channel | Don't have Notion or Slack connected? Use the **Scrunch only** tab below — you'll get the same analysis presented in the chat. *** Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, run this week's AI visibility brief. Step 1 — Pull the data: Get presence metrics for [brand name] for the last 14 days. Show me: - Overall presence rate this week vs. last week, with the percentage point change - Breakdown by AI platform (ChatGPT, Perplexity, Gemini, Claude, Google AI Overviews) — which platforms improved, which dropped - Sentiment comparison: this week vs. last week — any shift in the positive/negative balance - Share of voice vs. all tracked competitors — calculate each brand's presence rate and flag any competitor that moved more than 5 percentage points Step 2 — Find the week's most notable changes: Pull the 5 specific prompts with the biggest change in brand presence this week vs. last week — both the biggest gains and biggest drops. Show the prompt text, platform, and direction of change. Step 3 — Save to Notion: Create a new Notion page titled "[Monday's date] Weekly AI Brief — [brand name]" with this structure: - Headline metrics: overall presence %, week-over-week change, best and worst platform - Platform breakdown table - Sentiment snapshot - Competitive snapshot: share of voice table, any competitor that moved more than 5 points called out - Top 5 changes: the prompts with the biggest weekly movement, with context - Recommended action: one specific thing to address this week based on the data Step 4 — Post to Slack: Post this summary to the [#channel-name] Slack channel: "📊 [brand name] Weekly AI Brief — [date] Visibility: [X]% ([+/-Y]pp vs last week) [One sentence on the most notable finding this week] [One sentence recommended action] → Full brief: [link to the Notion page]" ``` **What you get:** A Notion page with all the detail and a Slack post with just what the team needs to act on. The Notion link in the Slack post connects the two. Run this every Monday and you have a permanent weekly archive without any manual work. Replace the bracketed values, then paste the whole thing into Claude. ```text theme={null} For [brand name] in Scrunch, run this week's AI visibility brief. Step 1 — Pull the data: Get presence metrics for [brand name] for the last 14 days. Show me: - Overall presence rate this week vs. last week, with the percentage point change - Breakdown by AI platform (ChatGPT, Perplexity, Gemini, Claude, Google AI Overviews) — which platforms improved, which dropped - Sentiment comparison: this week vs. last week — any shift in the positive/negative balance - Share of voice vs. all tracked competitors — calculate each brand's presence rate and flag any competitor that moved more than 5 percentage points Step 2 — Find the week's most notable changes: Pull the 5 specific prompts with the biggest change in brand presence this week vs. last week — both the biggest gains and biggest drops. Show the prompt text, platform, and direction of change. Step 3 — Save to Google Docs: Create a new Google Doc titled "[Monday's date] Weekly AI Brief — [brand name]" in [folder name or Drive location] with this structure: - Headline metrics: overall presence %, week-over-week change, best and worst platform - Platform breakdown table - Sentiment snapshot - Competitive snapshot: share of voice table, any competitor that moved more than 5 points called out - Top 5 changes: the prompts with the biggest weekly movement, with context - Recommended action: one specific thing to address this week based on the data Step 4 — Post to Slack: Post this summary to the [#channel-name] Slack channel: "📊 [brand name] Weekly AI Brief — [date] Visibility: [X]% ([+/-Y]pp vs last week) [One sentence on the most notable finding this week] [One sentence recommended action] → Full brief: [link to the Google Doc]" ``` **What you get:** A Google Doc with the full brief and a Slack post linking to it. Works well for teams that share everything through Google Drive and review docs in comment threads. No Notion or Slack? Paste this and get the full brief in the chat. ```text theme={null} For [brand name] in Scrunch, give me this week's AI visibility brief. Pull: 1. Overall presence rate this week vs. last week — the number and the change 2. Platform breakdown: presence rate per AI platform for both weeks, ranked by this week's performance 3. Sentiment this week vs. last week — any notable shift 4. Share of voice: [brand name] and all tracked competitors, this week vs. last week. Flag any brand that moved more than 5 points. 5. The 5 prompts with the biggest presence change this week — gains or drops, with prompt text and platform Present this as a structured brief. End with a single "Recommended action for this week" based on what you found. ``` *** ## Tips If you run this every Monday, name each page with the week date (e.g., "May 12 Weekly AI Brief — Acme Coffee") so they build into a searchable archive. You can ask Claude to link each week's page to a parent "AI Visibility" Notion database to create a timeline view. The Slack format above is intentionally minimal — it's built for a team channel where people skim. If you want a richer Slack post (with a table or more bullet points), add "Format the Slack post with a bullet list instead of a paragraph" to Step 4. Run the prompt once per brand, each in the same conversation. Claude will keep each brand's data separate and create individual Notion pages and Slack posts for each. *** Turn gap analysis into a prioritized Notion tracker with specific content recommendations. Explore 35+ ready-to-copy prompts for deeper analysis and reporting. # Weekly Visibility Alert to Slack Source: https://developers.scrunch.com/mcp/workflows/weekly-visibility-alert-slack Compare this week's presence, position, sentiment, and citation metrics to last week, and post a flagged alert to Slack when a threshold is crossed. Nobody wants a Slack message every week saying "nothing changed." This workflow only speaks up when something crosses a threshold you define — a real alert, not a status update disguised as one. **Tools used in this workflow** | Tool | Required? | Used for | | ----------- | --------- | --------------------------------------------------------- | | Scrunch MCP | Required | Week-over-week metric comparison | | Slack MCP | Required | Posting the alert (or the all-clear) to your team channel | Paste this in once a week — manually, or on a recurring schedule if your AI assistant supports one. *** ```text theme={null} For [brand name] in Scrunch, compare this week against last week and alert #[channel-name] on Slack only if something moved significantly. Step 1 — Compare the two weeks: Get presence, position, sentiment, and citation metrics for the last 7 days and the 7 days before that. Calculate the percentage-point change for each. Step 2 — Apply the threshold: Flag anything where: - Presence rate moved more than [5] percentage points in either direction - Sentiment (positive share) dropped more than [5] percentage points - A tracked competitor's share of voice increased by more than [10] percentage points - Citation share to [brand domain] dropped more than [5] percentage points Step 3 — Post to Slack: If anything was flagged in Step 2, post to #[channel-name]: "⚠️ [brand name] AI Visibility Alert — [date] [List each flagged metric with old value → new value and the change] Recommended check: [one sentence on what to look into first]" If nothing was flagged, post a short all-clear instead: "✅ [brand name] AI Visibility — [date]: no significant week-over-week movement. Presence [X]%, sentiment [Y]% positive." ``` **What you get:** A weekly Slack post that's either a real, specific alert worth acting on, or a one-line all-clear — never a wall of numbers nobody reads. *** ## Tips The percentage-point thresholds in Step 2 are starting points. If your brand's metrics are naturally noisy week to week, raise them to avoid false alarms; if you track a slower-moving, stable brand, tighten them so real movement doesn't get lost in the "no significant change" bucket. Extend Step 1 to also pull agent traffic totals for the same two weeks and flag a sudden drop in AI bot crawl volume — a crawl drop can be an early warning sign before it shows up in presence metrics. If you want sentiment drops to go to a different channel than competitive share-of-voice shifts, split Step 3 into per-metric posts with their own channel targets instead of one combined message. If the same metric gets flagged three weeks running, that's no longer a one-off — add a note to Step 3 asking Claude to call this out explicitly ("this is the third consecutive week presence has declined") so a recurring problem doesn't quietly become the new normal. *** Run the full competitive analysis when a share-of-voice alert fires. For a client-facing version of the same headline numbers, aimed outside the team.