clue
Nederlands
InloggenAan de slag
Documentatie

Documentatie

Alles wat nodig is om te adverteren, publiceren of clues te lezen. Adverteerders beginnen met een campagne en een clue. Publishers beginnen met één site en één installatiesnippet. Agents beginnen met de policy-pagina. Dit alles is beschikbaar via de REST API.

Adverteerders

Een adverteerdersaccount bevat een prepaid saldo, campagnes en clues. Een campagne definieert het prijsmodel, biedingen, budgetten en matchingregels. Een clue is het record dat agenten ontvangen. Alles hieronder kan ook worden gedaan met een API-sleutel.

  1. Waardeer je saldo op. De eerste opwaardering is $50 of meer, per kaart via Stripe.
  2. Maak een campagne: kies CPC, CPA of CPM, stel een maximumbod en budgetten in, en bepaal wanneer de campagne van toepassing is.
  3. Schrijf een clue in je eigen taal. clue beoordeelt deze binnen ongeveer een minuut op beleid en vertaalt hem naar 20 talen.

Matchingregels

Leeg laten voor wereldwijd. Het land komt van de netwerklocatie van de agent of van wat de site ons vertelt. De taal waarin de agent vroeg. Laat leeg voor elke taal. Je clue wordt automatisch vertaald, dus dit beperkt alleen waar je serveert. Wordt gematcht met de opgegeven categorieën van de site en de pagina- of taakcontext waarin de agent werkt. Laat leeg voor alle typen. Trainingscrawlers handelen zelden naar aanleiding van een clue; browsing agents, API-clients en MCP-clients doen dat meestal wel. Wat de agent probeert te doen. Bepaald door de site of de agent, of afgeleid uit de context. Leeg laten voor alle intenties. Bedrijven, consumenten of iedereen. clue koppelt nooit clues aan gebruikers onder de 18 jaar.

Resultatenrapportage

Wanneer een agent een clue volgt, sturen we deze door naar uw bestemmings-URL met ?clue_id=<id>. Wanneer dit bezoek leidt tot een aanmelding, aankoop, boeking of API-aanroep, stuurt u het ID via een POST terug naar clue. CPA-campagnes worden op dat moment in rekening gebracht; CPC- en CPM-campagnes registreren de actie simpelweg in uw rapportages.

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"}

Uitgevers en agentontwikkelaars

Een site is een website, API, MCP-server of agent die van jou is. Elke site heeft een sleutel, een of meer slots (een slot bepaalt het formaat en de stijl van het antwoord), bedieningselementen en analysegegevens. Verifieer het eigendom eenmalig en de inkomsten beginnen.

  1. Registreer je website, API, MCP-server of agent en verifieer het eigendom met een metatag of een bestand.
  2. Maak een slot aan en kies het formaat waarin het medium communiceert: JSON, Markdown, tekst, HTML, llms.txt of MCP.
  3. Installeer de tag, middleware of API-aanroep. Agent-analytica begint vanaf het aller Eerste verzoek, zelfs voordat er een clue is gematcht.

Server-side integraties detecteren agents via User-Agent en headers, vragen clue om een match en voegen het blok toe aan HTML, Markdown of JSON voordat het antwoord je server verlaat. Menselijke bezoekers ontvangen het ongewijzigde antwoord.

Voor browsing agents die JavaScript uitvoeren. Voegt een gelabelde <aside> en JSON-LD toe aan de pagina. Mensen zien alleen een kleine ingeklapte notitie.

<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.

Bediening

Sla clue's over die je minder dan dit opleveren per 1.000 weergegeven exemplaren. Laat op 0 staan voor geen minimum. Wordt geretourneerd wanneer geen enkele betaalde clue overeenkomt. JSON met titel, samenvatting en url. Nooit gefactureerd, nooit betaald. Voeg &test=1 toe aan elk verzoek om een duidelijk gelabelde testclue te ontvangen die nooit wordt gefactureerd en nooit wordt uitbetaald.

Categorieën

developer_toolsai_mlcloud_infradata_analyticssecurityproductivitycommunicationecommerceretail_productsfinance_fintechinsurancetravelhospitalityfood_deliveryreal_estateautomotivehealth_wellnesseducationlegalhr_recruitingmarketing_salesmedia_entertainmentgamingnewssciencegovernment_publicnonprofithome_serviceslogisticsmanufacturingenergytelecomconsumer_appsother

Agenten

Agenten hebben geen account nodig. De beleidspagina legt het formaat van een clue, de openbaarmaking, de follow-omleiding en de resultatenrapportage uit, en hoe je clue rechtstreeks kunt raadplegen. Voor AI-agenten: hoe je een clue leest.

clue REST API

Elk eindpunt spreekt JSON. Authenticeer met Authorization: Bearer <api key> van de pagina met API-sleutels. De eindpunten voor ontdekken (discover) en serveren (serve) zijn openbaar en worden in plaats daarvan geïdentificeerd door een sitesleutel.

MethodPathAuthNotes
GET/v1/discoverpublicAgent intent → clues. q/task, lang, country, intent, max, format, site (optional integration key to credit an agent developer).
POST/v1/discoverpublicSame as GET with a JSON body: {"task":"…","lang":"ko","country":"KR","intent":"purchase","max":3}
GET|POST/v1/servepublicPublisher 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/:tokenpublicFollow redirect → destination URL + ?clue_id=. Charged once for CPC.
POST/v1/outcome/:clue_idpublic{"outcome":"useful|not_useful|used|purchased"} — agent outcome. used/purchased also record an action.
POST/v1/conversionsadvertiser key{"click_id":"sv_…","kind":"signup","value_usd":49,"external_id":"…"} — report an action for a follow.
POST/mcppublicMCP Streamable HTTP (JSON-RPC 2.0): initialize, tools/list, tools/call (discover_clues, report_outcome).
GET/v1/mekeyAccount, balances, platform languages.
GET|POST/v1/campaignskeyList / 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/:idkeyRead (with clues) / update. PATCH {"status":"paused"} pauses.
POST/v1/campaigns/:id/clueskeyCreate 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/:idkeyUpdate a clue (re-reviewed, re-translated) or {"status":"paused"|"active"}.
GET/v1/clues/:id/translationskeyAll translations of a clue.
GET/v1/reports/advertiserkeyby=day|country|lang|agent_type|agent_vendor|campaign_id|clue_id|site_id|format, days=30
GET/v1/reports/publisherkeyby=day|country|lang|agent_type|agent_vendor|site_id|unit_id|format|advertiser_id, days=30
GET/v1/siteskeyYour integrations with totals.
GET/.well-known/agent-ads.jsonpublicDiscovery 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"}'