Use
Events and goals
Track what matters on your site, and see who does it: people, people sent by AI assistants, or agents. Every event joins the visit it belongs to and carries that visit's label, so "sign-ups by agents" never inflates "sign-ups by people".
Sending events
From the page (browser snippet):
<script>
// Optional: queue calls made before the snippet loads.
window.punchline = window.punchline || { q: [] };
window.punchline.track = window.punchline.track || function () { window.punchline.q.push(["track", ...arguments]); };
</script>
<button onclick="punchline.track('book_demo', { plan: 'team' })">Book a demo</button>
The snippet also records two events automatically, with GA4's names: click for outbound links (outbound: true, link_domain) and file_download (file_extension, link_domain). Never query strings, link text or anything typed.
From your servers (POST /v1/events, a key with the events:write scope):
curl -s https://app.punchlineanalytics.com/v1/events \
-H "Authorization: Bearer $PUNCHLINE_WRITE_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-8431" \
-d '{
"site_id": "<your site id>",
"events": [
{ "name": "purchase", "value": 249, "props": { "plan": "team" },
"visitor": { "ip": "203.0.113.7", "user_agent": "Mozilla/5.0 …" } }
]
}'
Include visitor (the visitor's IP and user agent, as your server saw them) to tie the event to their visit; Punchline uses them in memory only, as it does for page views. Without it, the event counts as not tied to a visit. Add company_domain (the domain of a work email someone gave you) to connect that visit, and agents working in the same browser that day, to a company: see Accounts. Up to 1,000 events per request, timestamps within the last 36 hours, and Idempotency-Key makes retries safe.
Rules for every event: names use letters, digits and _ and start with a letter (GA4-compatible, max 40); up to 10 properties, each a string (max 100 characters), number or boolean. Email addresses are removed from properties and paths.
GA4-compatible events
Punchline takes GA4 events as they are, so a goal can count the same conversion GA4 does:
- Name: use GA4's name, such as
purchase,generate_lead,sign_uporbegin_checkout(letters, digits and_, up to 40 characters, starting with a letter). - Value and currency: GA4's
valueis the third argument andcurrencygoes in the properties:punchline.track('purchase', { currency: 'USD' }, 249). - Other GA4 parameters (items, transaction IDs, user properties) aren't needed and shouldn't be sent: they can carry personal data.
With Google Tag Manager, the Punchline template does this without code. Switch from GA4 in the dashboard lists your GA4 key events and creates the matching goals.
Triggers: events without code
In Site settings → Event triggers, create events from what visitors do:
| Trigger | Works with | Example |
|---|---|---|
| Page view | Every install | /pricing (everything under it) or =/pricing (just that page) |
| URL match | Every install | /blog/*/comments |
| Click | Browser snippet | CSS selector #book-demo |
| Form submit | Browser snippet | CSS selector form.newsletter (only that it was submitted; never the fields) |
Changing a trigger gives it a new version, and each event records the version that produced it, so a count never silently changes meaning. Pause a trigger to stop it without losing its history.
Goals and conversions
A goal is an event (sign_up) or a page (/thank-you). A conversion is a session that reaches it, credited to how that session arrived: its channel, campaign, referrer and landing page. The Goals report shows conversions and conversion rates for people, AI-referred people and agents, by channel. In Agent content, the funnel's last stage, converted, counts people sent by AI assistants who then completed a goal.
Query conversions yourself:
{
"date_range": { "from": "2026-09-01", "to": "2026-09-30" },
"metrics": ["conversions", "conversion_rate"],
"dimensions": ["goal", "channel"],
"filters": [["visitor_type", "neq", "agent"]]
}
or events:
{
"date_range": { "from": "2026-09-01", "to": "2026-09-30" },
"metrics": ["events", "event_value"],
"dimensions": ["event_name", "visitor_type"]
}
Page, event and conversion metrics are separate families: one family per query.
Did an AI assistant help? (survey)
Links show only part of AI's influence: someone asks ChatGPT for a shortlist, then types your address days later and arrives as "direct". One question after a conversion sizes the rest, the way podcast advertisers ask "how did you hear about us?".
On your thank-you page, with the browser snippet installed, add an element and ask:
<div id="ai-question"></div>
<script>punchline.survey("#ai-question");</script>
It shows Did an AI assistant (like ChatGPT, Claude or Perplexity) help you find or choose us? with Yes, No and Not sure, sends one event for the answer and says thanks. It's plain markup with pl-survey class names for you to style; change the wording with punchline.survey("#ai-question", { question: "…", thanks: "…" }). Nothing is stored in the browser.
From your server or email survey, send the events yourself: ai_assist_yes, ai_assist_no or ai_assist_not_sure.
What you see on Goals & events → Did an AI assistant help?: the share who said yes (with a 95% interval), estimated AI-assisted conversions (people's conversions × that share), what Punchline connects directly (conversions by people sent from AI assistants, plus converted handoff links), and the multiplier between the two. The estimate appears from 30 answers and is never mixed into observed numbers. Also at GET /v1/ai-influence and the MCP tool get_ai_influence.
Ask the docs
Answers come from these docs only, written by Claude (Anthropic). Your question is sent to answer it, and isn't stored.