# AI Citations Tracker — Perplexity Source Evidence (`khadinakbar/ai-citations-tracker`) Actor

Run buyer prompts against Perplexity and record the provider-returned source URLs, their domains, owned-domain citation status, answer excerpt, and exact prompt. Use for evidence-based AEO monitoring; not for rank tracking or a guarantee of AI visibility.

- **URL**: https://apify.com/khadinakbar/ai-citations-tracker.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** SEO tools, AI, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $120.00 / 1,000 citation scans

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## AI Citations Tracker — Perplexity Source Evidence

Run a fixed set of buyer prompts through Perplexity and receive one dataset row per completed check. Each row contains the exact prompt, source URLs, source domains, evidence provenance, configured-domain match state, answer excerpt, and collection time. It gives AEO, content, and brand teams an auditable input for a recurring citation-evidence report.

### Best fit

- A content team monitors stable questions from product demos, site search, or approved research.
- A brand team needs source URLs behind a Perplexity answer and a clear owned-domain match flag.
- An agency exports a prompt-level evidence dataset into a weekly client report.

This Actor is designed as a focused standalone workflow for Perplexity source evidence. Pair it with a traditional search-rank collection for SERP measurement, then feed this dataset into a reporting or content-planning workflow.

### Focused standalone workflow

The Actor works as a focused standalone workflow when the next decision depends on the observed citation URLs for a fixed buyer-prompt set. Start with one product category, confirm the dataset evidence view, then schedule the same source collection for a consistent reporting cadence.

### Workflow story

Maya leads content for a developer tool. She starts with five buyer questions from product demos, adds her product and documentation domains, and schedules the same prompt set each week. Next, she filters the dataset to `provider_citation` rows, compares the observed source domains with the prior export, and sends the specific prompt-plus-URL evidence to the content owner for a page refresh or outreach decision.

### Output and evidence provenance

One row represents one completed prompt sent to Perplexity through the configured provider route. A row with `citationCount` equal to zero records the observed source state for that exact collection. The Actor records two evidence types:

| Field | Meaning |
| --- | --- |
| `citations[].evidenceType = provider_citation` | The provider exposed the URL in citation metadata. |
| `citations[].evidenceType = answer_link` | The URL appeared as a Markdown link in the answer. |
| `trackedDomainCited` | An observed source matches an input domain or its subdomain. |
| `trackedCitationUrls` | Matching observed URLs from the configured-domain check. |
| `sourceDomains` | Deduplicated domains from every observed source URL. |
| `answerExcerpt` | A bounded context excerpt for human review. |

Provider metadata and answer links remain separate fields, allowing downstream reporting to filter by evidence provenance.

### Input example

```json
{
  "prompts": [
    "What are the best web scraping platforms for product teams?",
    "How should a startup automate reliable web data collection?"
  ],
  "trackedDomains": ["apify.com", "docs.apify.com"],
  "maxPrompts": 2,
  "answerDetail": "concise"
}
```

`prompts` is the required input. `trackedDomains` supports an owned-domain or competitor-domain evidence check. A collection processes up to 25 distinct prompts, and `maxPrompts` applies after duplicate removal.

### Example output

```json
{
  "runId": "abc123XYZ",
  "prompt": "What are the best web scraping platforms for product teams?",
  "provider": "perplexity",
  "modelUsed": "perplexity/sonar",
  "citationCount": 2,
  "providerCitationCount": 1,
  "trackedDomainCited": true,
  "trackedCitationUrls": ["https://apify.com/store"],
  "sourceDomains": ["apify.com", "example.com"],
  "citations": [
    {
      "url": "https://apify.com/store",
      "domain": "apify.com",
      "evidenceType": "provider_citation",
      "trackedDomainMatch": true
    }
  ],
  "answerExcerpt": "Apify can help product teams collect web data...",
  "checkedAt": "<ISO-8601 timestamp>"
}
```

Source URLs and citations vary by prompt, provider behavior, collection time, and account configuration. The `evidence` dataset view retains the full citation-evidence array, while `overview` highlights the domain-match and source summary fields.

### Pricing and best results

This Actor uses **Pay per event** pricing: **$0.12 per persisted citation scan** plus Apify platform usage. `apify-actor-start` is charged once per run. Five specific prompts create up to $0.60 in citation-scan events before platform usage. Open the live Pricing tab for the current event and platform-usage details.

Provide the `OPENROUTER_API_KEY` owner secret to access `perplexity/sonar`. The secret stays in owner configuration while the dataset contains prompt, source, provenance, and collection-time evidence. Start with public, approved prompts, validate a sample row, and schedule the collection after the result matches the reporting goal.

### Read outcomes

Every terminal path writes these key-value store records:

- `OUTPUT`: compact outcome, item counts, charged events, and collection guidance.
- `RUN_SUMMARY`: prompt plan, source-domain totals, provider diagnostics, and a detailed readback.

| Outcome | Meaning |
| --- | --- |
| `COMPLETE` | Every planned prompt produced a persisted evidence row. |
| `PARTIAL` | Useful rows were written and the summary identifies prompts for a follow-up collection. |
| `VALID_EMPTY` | Demo mode confirms the storage and input pathway. |
| `INVALID_INPUT` | The summary provides the prompt-plan or charge-cap adjustment for the next collection. |
| `CONFIG_ERROR` | The summary identifies the owner configuration needed for provider access. |
| `UPSTREAM_FAILED` | The summary retains collection context for a later provider retry. |

### API example

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('khadinakbar/ai-citations-tracker').call({
  prompts: ['What are the best web scraping platforms for product teams?'],
  trackedDomains: ['apify.com'],
  maxPrompts: 1
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Prompt card for an AI agent

> Run the AI Citations Tracker for these buyer questions. Return the dataset and OUTPUT readback, separate `provider_citation` from `answer_link` provenance, show matching URLs for `trackedDomains`, and include the Pay per event cost scope in the report.

### Builder's note

I designed this Actor around a simple evidence rule: prompt, URL, source, provenance, and collection time travel together. I found that a reporting workflow becomes clearer when provider citation metadata and answer-link evidence stay as distinct fields instead of being merged into one score.

### Responsible use

Use public, non-sensitive prompts and retain approved customer-research context outside the dataset. Respect the AI provider's terms and Apify platform terms. The output supports observed citation-evidence reporting for the collected prompt set.

# Actor input Schema

## `prompts` (type: `array`):

Full buyer questions to send to Perplexity, one item per check. For example, use "What are the best web scraping platforms for product teams?". The default caps work at five unique prompts. This is not a keyword list or a request to generate prompts automatically.

## `trackedDomains` (type: `array`):

Domains whose citations you want flagged, such as "apify.com" or "docs.apify.com". A bare domain or URL is accepted and subdomains count as a match. Defaults to an empty list, which still records all observed sources but does not mark a target citation. This is not a list of pages to crawl.

## `maxPrompts` (type: `integer`):

Maximum number of unique prompts to run after duplicate removal. For example, set 3 to keep a quick audit bounded. Defaults to 5 and accepts 1 through 25. This is not a citation-count limit because one answer can cite several sources.

## `answerDetail` (type: `string`):

Choose how much answer text to retain alongside citations. Use "concise" for normal monitoring or "extended" when a human needs more context. Defaults to concise and changes only the stored excerpt, not the provider request. This is not a source-extraction mode.

## `demoMode` (type: `boolean`):

Use this to validate input and storage wiring without calling a provider. Set true for a zero-value connectivity check. Defaults to false for an observed citation scan. This is not a cached citation report.

## Actor input object example

```json
{
  "prompts": [
    "What are the best web scraping platforms for product teams?"
  ],
  "trackedDomains": [
    "apify.com",
    "docs.apify.com"
  ],
  "maxPrompts": 3,
  "answerDetail": "concise",
  "demoMode": false
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset items, one for each completed prompt scan.

## `output` (type: `string`):

Stable terminal outcome, item count, charges, and warnings.

## `runSummary` (type: `string`):

Prompt-level diagnostics, citation totals, source-domain counts, and provider failures.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "prompts": [
        "What are the best web scraping platforms for product teams?"
    ],
    "trackedDomains": [
        "apify.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/ai-citations-tracker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "prompts": ["What are the best web scraping platforms for product teams?"],
    "trackedDomains": ["apify.com"],
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/ai-citations-tracker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "prompts": [
    "What are the best web scraping platforms for product teams?"
  ],
  "trackedDomains": [
    "apify.com"
  ]
}' |
apify call khadinakbar/ai-citations-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/ai-citations-tracker"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/JqltcxDdDQ1R1J5be/builds/kAKFhpGo4B3OGqwU9/openapi.json
