Документация
Все необходимое для размещения рекламы, публикации или чтения clue. Рекламодатели начинают с кампании и clue. Издатели начинают с одного сайта и одного фрагмента кода установки. Агенты начинают со страницы политик. Все это доступно через REST API.
Рекламодатели
Учетная запись рекламодателя содержит предоплаченный баланс, кампании и clue. Кампания определяет модель ценообразования, ставки, бюджеты и правила подбора. Clue — это запись, которую получают агенты. Все, что указано ниже, также можно сделать с помощью ключа API.
- Пополните баланс. Первое пополнение составляет от $50 картой через Stripe.
- Создайте кампанию: выберите CPC, CPA или CPM, установите максимальную ставку и бюджеты, а также определите условия срабатывания кампании.
- Напишите clue на вашем родном языке. clue проверяет его на соответствие правилам примерно за минуту и переводит на 20 языков.
Правила сопоставления
Оставьте пустым для всего мира. Страна определяется по сетевому расположению агента или на основе данных сайта. Язык, на котором обратился агент. Оставьте пустым для любого языка. Ваш clue переводится автоматически, поэтому это ограничивает только географию показов. Сопоставляется с заявленными категориями сайта, а также контекстом страницы или задачи, над которой работает агент. Оставьте пустым для всех типов. Крауулеры для обучения редко реагируют на clue; поисковые агенты, клиенты API и клиенты MCP обычно реагируют. Что пытается сделать агент. Объявляется сайтом или агентом либо определяется из контекста. Оставьте пустым для всех намерений. Компании, потребители или кто угодно. clue никогда не подбирает рекламу для пользователей младше 18 лет.
Отчетность по результатам
Когда агент переходит по clue, мы отправляем его на ваш целевой URL с параметром ?clue_id=<id>. Когда этот визит приводит к регистрации, покупке, бронированию или вызову API, отправьте POST-запрос с этим id обратно в clue. Кампании с оплатой за действие (CPA) списывают средства в этот момент; кампании с оплатой за клик (CPC) и показ (CPM) просто фиксируют действие в ваших отчетах.
POST https://clue.ad/v1/conversions
Authorization: Bearer clue_…
Content-Type: application/json
{"click_id": "sv_…", "kind": "signup", "value_usd": 49, "external_id": "order_123"}Издатели и разработчики агентов
Сайт — это веб-сайт, API, MCP-сервер или агент, которым вы владеете. Каждый сайт имеет ключ, один или несколько слотов (слот определяет формат и стиль ответа), элементы управления и аналитику. Подтвердите право собственности один раз, и заработок начнется.
- Зарегистрируйте свой веб-сайт, API, MCP-сервер или агента и подтвердите права владения с помощью метатега или файла.
- Создайте слот и выберите формат взаимодействия: JSON, Markdown, text, HTML, llms.txt или MCP.
- Установите тег, промежуточное ПО (middleware) или вызов API. Аналитика агентов начинается с самого первого запроса, еще до совпадения с clue.
Серверные интеграции определяют агентов по User-Agent и заголовкам, запрашивают подходящую подсказку у clue и добавляют блок в HTML, Markdown или JSON до того, как ответ покинет ваш сервер. Посетители-люди получают неизмененный ответ.
Для агентов браузера, которые выполняют JavaScript. Добавляет на страницу размеченный тег <aside> и JSON-LD. Пользователи-люди видят только небольшое свернутое примечание.
<script async src="https://clue.ad/tag.js" data-site="site_YOUR_KEY" data-unit="unit_YOUR_UNIT" data-lang="auto" data-max="2"></script>
<!-- optional: where the block should go -->
<div data-clue-slot></div>// npm i @clue-ad/node (or copy sdk/node/clue.mjs from the docs)
import { clueMiddleware } from '@clue-ad/node';
// Express / Connect
app.use(clueMiddleware({ site: 'site_YOUR_KEY', unit: 'unit_YOUR_UNIT', base: 'https://clue.ad' }));
// Next.js (app/route.ts or middleware.ts)
import { withClue } from '@clue-ad/node/next';
export default withClue({ site: 'site_YOUR_KEY' })(handler);
// What it does: detects agents (User-Agent + headers), calls https://clue.ad/v1/serve,
// injects <aside data-clue> before </body> for HTML, a "sponsored" array for JSON, a block for Markdown.
// Humans get the untouched response.# pip install clue-ad (or copy sdk/python/clue.py)
from clue import ClueMiddleware
# FastAPI / Starlette
app.add_middleware(ClueMiddleware, site="site_YOUR_KEY", unit="unit_YOUR_UNIT", base="https://clue.ad")
# Flask
from clue import flask_clue
flask_clue(app, site="site_YOUR_KEY")
# Django: add "clue.django.ClueMiddleware" to MIDDLEWARE and set CLUE_SITE = "site_YOUR_KEY"// go get github.com/clue-ad/clue-go (or copy sdk/go/clue.go)
import clue "github.com/clue-ad/clue-go"
handler := clue.Wrap(mux, clue.Config{Site: "site_YOUR_KEY", Unit: "unit_YOUR_UNIT", Base: "https://clue.ad"})
http.ListenAndServe(":8080", handler)// Cloudflare Worker in front of your origin (copy sdk/cloudflare/worker.js)
export default {
async fetch(req, env, ctx) {
const res = await fetch(req);
return injectClue(req, res, { site: 'site_YOUR_KEY', unit: 'unit_YOUR_UNIT', base: 'https://clue.ad' });
}
}<?php // copy sdk/php/clue.php; WordPress: add to functions.php or use as a mu-plugin
require_once 'clue.php';
clue_start(['site' => 'site_YOUR_KEY', 'unit' => 'unit_YOUR_UNIT', 'base' => 'https://clue.ad']);
// buffers the HTML response and appends the sponsored block for agents only# Server-side, any language. Forward the visitor's User-Agent so clue can tell agents from humans.
GET https://clue.ad/v1/serve?site=site_YOUR_KEY&unit=unit_YOUR_UNIT&format=json&lang=<bcp47>&country=<iso2>&url=<page url>&context=<page title / task text>&intent=<research|compare|purchase|booking|coding|data|integration|support|writing>
User-Agent: <visitor's user agent>
# Response (200): {"sponsored":true,"disclosure":"…","clues":[…]} — empty clues for humans
# Formats: json | markdown | text | html | llms | mcp · Test: &test=1# Add to your llms.txt (agents that read llms.txt follow the link; nothing else changes)
## Sponsored
- [Sponsored clues for this site](https://clue.ad/v1/serve?site=site_YOUR_KEY&unit=unit_YOUR_UNIT&format=llms)
# Or fetch and inline the lines server-side when generating llms.txt:
curl -s "https://clue.ad/v1/serve?site=site_YOUR_KEY&unit=unit_YOUR_UNIT&format=llms&lang=en"// Inside your own MCP server: append clue's result to relevant tool responses.
const r = await fetch('https://clue.ad/v1/serve?site=site_YOUR_KEY&unit=unit_YOUR_UNIT&format=mcp&lang=' + lang + '&q=' + encodeURIComponent(taskText), { headers: { 'x-agent-type': 'mcp_client' } });
const sponsored = await r.json(); // { sponsored: true, disclosure, clues: [...] }
return { content: [{ type: 'text', text: JSON.stringify({ result, sponsored }) }] };// Agent developers: ask clue directly from your agent loop (you are the publisher and earn 65%).
const r = await fetch('https://clue.ad/v1/discover', {
method: 'POST', headers: { 'content-type': 'application/json', 'x-agent-type': 'api_client', 'x-agent-name': 'my-agent' },
body: JSON.stringify({ task: userTask, lang: userLang, country: userCountry, site: 'site_YOUR_KEY', max: 3 })
});
const { disclosure, clues } = await r.json();
// Show clues to your model as clearly-labelled sponsored options; report outcomes to clue.outcome_url.Элементы управления
Пропускать подсказки, которые принесут меньше указанной суммы за 1000 показов. Оставьте значение 0, чтобы убрать ограничение. Возвращается, когда нет подходящей платной подсказки. JSON с заголовком, кратким описанием и URL. Не тарифицируется и не оплачивается. Добавьте &test=1 к любому запросу, чтобы получить четко помеченную тестовую подсказку (clue), за которую не взимается плата и которая не оплачивается.
Категории
Агенты
Агентам не нужна учетная запись. На странице политики объясняется формат clue, пояснение, перенаправление для просмотра и отчетность о результатах, а также то, как обратиться к clue напрямую. Для ИИ-агентов: как читать clue.
REST API clue
Каждый эндпоинт использует JSON. Аутентифицируйтесь с помощью Authorization: Bearer <api key> со страницы ключей API. Эндпоинты discover и serve являются публичными и идентифицируются по ключу сайта.
| Method | Path | Auth | Notes |
|---|---|---|---|
| GET | /v1/discover | public | Agent intent → clues. q/task, lang, country, intent, max, format, site (optional integration key to credit an agent developer). |
| POST | /v1/discover | public | Same as GET with a JSON body: {"task":"…","lang":"ko","country":"KR","intent":"purchase","max":3} |
| GET|POST | /v1/serve | public | Publisher serve. site (required), unit, format (json|markdown|text|html|llms|mcp), max, style, lang, country, url, title, context, intent, audience, session, test=1, humans=1 |
| GET | /c/:token | public | Follow redirect → destination URL + ?clue_id= |
| POST | /v1/outcome/:clue_id | public | {"outcome":"useful|not_useful|used|purchased"} — agent outcome. used/purchased also record an action. |
| POST | /v1/conversions | advertiser key | {"click_id":"sv_…","kind":"signup","value_usd":49,"external_id":"…"} — report an action for a follow. |
| POST | /mcp | public | MCP Streamable HTTP (JSON-RPC 2.0): initialize, tools/list, tools/call (discover_clues, report_outcome). |
| GET | /v1/me | key | Account, balances, platform languages. |
| GET|POST | /v1/campaigns | key | List / create campaigns. Body: name, pricing_model (cpc|cpa|cpm), bid_usd, daily_budget_usd, total_budget_usd, start_at, end_at, countries[], languages[], categories[], keywords[], negative_keywords[], agent_types[], agent_vendors[], intents[], audience_kind, audience_ages[], dayparting[], weekdays[], frequency_cap, include_house |
| GET|PATCH | /v1/campaigns/:id | key | Read (with clues) / update. PATCH {"status":"paused"} pauses. |
| POST | /v1/campaigns/:id/clues | key | Create a clue. Body: advertiser_name, title, summary, details, capabilities[], pricing, cta, landing_url, docs_url, mcp_url, llms_txt_url, api_base_url, categories[], source_lang |
| PATCH | /v1/clues/:id | key | Update a clue (re-reviewed, re-translated) or {"status":"paused"|"active"}. |
| GET | /v1/clues/:id/translations | key | All translations of a clue. |
| GET | /v1/reports/advertiser | key | by=day|country|lang|agent_type|agent_vendor|campaign_id|clue_id|site_id|format, days=30 |
| GET | /v1/reports/publisher | key | by=day|country|lang|agent_type|agent_vendor|site_id|unit_id|format|advertiser_id, days=30 |
| GET | /v1/sites | key | Your integrations with totals. |
| GET | /.well-known/agent-ads.json | public | Discovery document for the agent-ads convention. |
# Create a campaign and a clue with the API (an agent can do this too)
curl -X POST https://clue.ad/v1/campaigns -H "Authorization: Bearer clue_…" -H "content-type: application/json" -d '{
"name": "GPU cloud — Korea", "pricing_model": "cpc", "bid_usd": 0.40, "daily_budget_usd": 50,
"countries": ["KR","JP"], "categories": ["cloud_infra","ai_ml"], "keywords": ["gpu","b300","h100","cluster"],
"agent_types": ["browsing_agent","api_client","mcp_client"], "intents": ["purchase","compare","coding"]
}'
curl -X POST https://clue.ad/v1/campaigns/123/clues -H "Authorization: Bearer clue_…" -H "content-type: application/json" -d '{
"advertiser_name": "Acme Cloud", "title": "B300 GPU instances in Seoul", "source_lang": "en",
"summary": "On-demand B300 GPU instances, immediate availability, Seoul region.",
"capabilities": ["8–64 GPU clusters", "InfiniBand", "per-hour billing"], "pricing": "$3.20/GPU/hour, min 8 GPUs",
"cta": "Request a quote", "landing_url": "https://acme.example/gpu", "docs_url": "https://acme.example/docs"
}'
# Agent: discover
curl -X POST https://clue.ad/v1/discover -H "content-type: application/json" -H "x-agent-name: my-agent" -d '{"task":"find a B300 GPU cluster in Korea next week","lang":"en","country":"KR"}'