Documentazione
Tutto il necessario per fare pubblicità, pubblicare o leggere clue. Gli inserzionisti iniziano con una campagna e un clue. Gli editori iniziano con un sito e un frammento di installazione. Gli agenti iniziano con la pagina delle policy. Tutto è disponibile tramite l'API REST.
Inserzionisti
Un account inserzionista detiene un saldo prepagato, campagne e clue. Una campagna definisce il modello di prezzo, le offerte, i budget e le regole di corrispondenza. Un clue è il record che gli agenti ricevono. Tutto quanto sotto può essere fatto anche con una chiave API.
- Ricarica il saldo. La prima ricarica è di $50 o più, con carta tramite Stripe.
- Crea una campagna: scegli CPC, CPA o CPM, imposta un'offerta massima e i budget, e definisci quando la campagna deve essere considerata.
- Scrivi un clue nella tua lingua. clue ne verifica la conformità alle norme in circa un minuto e lo traduce in 20 lingue.
Regole di abbinamento
Lascia vuoto per tutto il mondo. Il paese deriva dalla posizione di rete dell'agente o da quanto comunicato dal sito. La lingua richiesta dall'agente. Lascia vuoto per qualsiasi lingua. Il tuo clue viene tradotto automaticamente, quindi questo limita solo dove effettui la pubblicazione. Abbinati alle categorie dichiarate del sito e al contesto della pagina o dell'attività in cui l'agente sta operando. Lascia vuoto per tutti i tipi. I crawler di addestramento raramente agiscono su un clue; gli agent di navigazione, i client API e i client MCP di solito lo fanno. Cosa l'agente sta cercando di fare. Dichiarato dal sito o dall'agente, o dedotto dal contesto. Lascia vuoto per tutti gli intenti. Aziende, consumatori o chiunque. clue non abbinerà mai clue a utenti di età inferiore a 18 anni.
Rapporto sui risultati
Quando un agente segue un clue, lo inviamo al tuo URL di destinazione con ?clue_id=<id>. Quando quella visita si trasforma in una registrazione, un acquisto, una prenotazione o una chiamata API, fai una POST dell'id a clue. Le campagne CPA vengono addebitate in quel momento; le campagne CPC e CPM registrano semplicemente l'azione nei tuoi rapporti.
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"}Editori e sviluppatori di agenti
Un sito è un sito Web, un'API, un server MCP o un agente di tua proprietà. Ogni sito ha una chiave, uno o più slot (uno slot definisce il formato e lo stile della risposta), controlli e analisi. Verifica la proprietà una volta e inizia a guadagnare.
- Registra il tuo sito web, API, server MCP o agente e verifica la proprietà con un meta tag o un file.
- Crea uno slot e scegli il formato supportato dalla superficie: JSON, Markdown, testo, HTML, llms.txt o MCP.
- Installa il tag, il middleware o la chiamata API. Le analisi degli agenti iniziano fin dalla prima richiesta, ancor prima che un clue corrisponda.
Le integrazioni lato server rilevano gli agenti tramite User-Agent e intestazioni, richiedono una corrispondenza a clue e aggiungono il blocco a HTML, Markdown o JSON prima che la risposta lasci il tuo server. I visitatori umani ricevono la risposta intatta.
Per agenti di navigazione che eseguono JavaScript. Aggiunge un <aside> etichettato e JSON-LD alla pagina. Gli utenti umani vedono solo una piccola nota compressa.
<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.Controlli
Salta i clue che ti farebbero guadagnare meno di questa cifra ogni 1.000 visualizzazioni. Lascia a 0 per nessun minimo. Restituito quando nessun clue a pagamento corrisponde. JSON con titolo, riepilogo e URL. Mai fatturato, mai pagato. Aggiungi &test=1 a qualsiasi richiesta per ricevere un clue di test chiaramente etichettato che non viene mai fatturato né pagato.
Categorie
Agenti
Gli agenti non hanno bisogno di un account. La pagina delle policy spiega il formato di un clue, la divulgazione, il reindirizzamento del follow e la reportistica degli esiti, e come chiedere direttamente a clue. Per gli agenti AI: come leggere un clue.
API REST di clue
Ogni endpoint comunica in JSON. Effettua l'autenticazione con Authorization: Bearer <api key> dalla pagina delle chiavi API. Gli endpoint di scoperta e erogazione sono pubblici e identificati invece da una chiave del sito.
| 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"}'