Skip to content
New storyWe built Skald to count visitors. It caught an AI-key thief.
SkaldEvery visit, truly told.

Integrations · webhooks in and out

Analytics webhooks: signed leads in, conversions and alerts out

Analytics webhooks in Skald work both ways. Calendly, Cal.com, HubSpot, Typeform, Stripe, Zapier, Make and your own server send each lead signed; Skald sends conversions and alerts to your CRM, Zapier or Slack, never with a name or an email.

Analytics webhooks are messages one tool posts to another's address the moment something happens: a booking, a payment, a form, an alert. Each Skald hook has its own address and secret, checks the signature before it keeps anything, and keeps each conversion once. One of the Skald integrations.

30-day free trial · no card · we set it up within one working day · free to self-host

integrations › last deliveries · sample5 rows
  1. 09:02 stripe · checkout.session.completedkept
  2. 09:02 stripe · the same event againalready had it
  3. 10:15 json · from Zapier, Bearer keykept
  4. 11:31 lead · time 9 minutes offbad signature
  5. 11:44 typeform · Send a test eventtest, read and not kept

Sample deliveries. Each message a hook received, with its outcome in words.

[01] webhooks in

Incoming webhooks for bookings, forms and payments

Each tool gets its own address and its own secret on Settings › Integrations. Pick a tool: who makes the secret, which events to send, and what Skald counts. Every lead lands in lead attribution.

pick a tool

Calendly: either side makes the secret

Send invitee.created, invitee.canceled and invitee_no_show.created. A booking counts as Demos, completed; a cancellation as cancelled or rescheduled; a no-show as no-show. Calendly sends webhooks on its paid plans, made through its API.

[02] signed, or refused

Webhook signature verification, before anything is kept

A hook does nothing until it has a secret: its address answers "not found". Once it has one, every message is checked against it before it is read.

  • Your server signs with X-Skald-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256> of the time, a dot and the raw body.
  • A time more than 5 minutes off Skald's clock is refused.
  • No-code tools may send the secret as a plain key instead, on the json and lead hooks only, and only without a signature header.
  • Leaked? Rotate secret: the old one stops at once.

Make can sign too; the formula is in the webhooks help page.

a signed test lead · your values in < >
$ BODY='{"external_ref":"L-1001","action":"demo"}'
$ T=$(date +%s)
$ SIG=$(printf '%s.%s' "$T" "$BODY" \
    | openssl dgst -sha256 -hmac "<your-secret>" -hex | sed 's/^.* //')
$ curl -X POST 'https://stats.example.com/traffic-hooks/example.com/lead' \
    -H 'Content-Type: application/json' \
    -H "X-Skald-Signature: t=$T,v1=$SIG" --data-raw "$BODY"

Copy the address from your own Integrations page. Keep the secret out of email, chat and tickets.

[03] retries are harmless

Webhook retries and duplicates, counted once

A tool sends again when it does not get an OK. That is fine: Skald keeps each conversion once per tool, reference and stage, and answers a repeat OK.

Cal.com and Typeform sign no time, so Skald also remembers each of their messages for 30 days and ignores an exact repeat. If Skald cannot save a message, it answers with an error, so the tool sends it again later. One limit is yours to keep: the same lead sent through two tools counts twice. The Status list names it.

last deliveries · outcome · samplelast 50 kept
  1. keptrecorded
  2. already had ita repeat, nothing to do
  3. not a conversionan event Skald does not count
  4. bad signaturepaste or rotate the secret
  5. too largeover 64 KB
  6. too manyover 60 a minute; the tool retries

[04] webhooks out

Outgoing webhooks to your CRM, Zapier or Slack

Paste an https:// address, tick the events, press Add webhook, and copy the secret shown once. Send a test checks the address answers.

  • conversion.started, .completed, .cancelled, .rescheduled, .no_show, .abandoned
  • lead.won, lead.lost
  • ai.reading_changed: an assistant started or stopped reading a page
  • alert.opened: any alert, when it opens

Only events after you add the webhook are sent. A failed delivery is tried again for about 15 hours. Remove stops it at once. A Slack address gets Slack's own shape.

conversion.completed · sample body
{"event": "conversion.completed", "id": "<same on every retry>",
 "site": "example.com", "action": "demo", "stage": "completed",
 "at": "2026-10-20T14:30:00-04:00", "tool": "calendly",
 "external_ref": "<the tool's reference>", "vid": "skv_<id>",
 "source_type": "AI assistant", "first_source": "chatgpt.com",
 "campaign": null, "landing": "/docs/setup/",
 "country": "CA", "device": "Desktop",
 "visits_before": 2, "seconds_to_convert": 5400,
 "journey": [{"at": "…", "path": "/docs/setup/", "source_type": "AI assistant"},
             {"at": "…", "path": "/pricing/", "source_type": "This site"}]}

Sample body. A summary, never a name or an email; the journey is anonymous, at most 50 page views.

[05] what is kept

What Skald keeps from a webhook, and what it drops

Only what attribution needs, and a cut-down copy so every figure can be counted a second time.

  • Kept: the action, its stage, the time, the tool, its own reference, the visitor ID when visitor IDs are on, and the source, campaign, landing page, country and device when known.
  • Kept for checking: a copy of each verified message, cut down to the fields Skald reads, as long as the leads.
  • Always dropped: IP addresses, browser strings, phone numbers, extra emails, form answers, customer details, and Calendly's cancel and reschedule links.
  • Names and emails: kept only when the site's setting keeps them.
  • The delivery log: when, the outcome and the answer, never the message. Kept 90 days.

[06] what it does not do

What Skald webhooks do not do

Signed, once, and plain about it. Here is what that leaves out.

What it does not do

  • The same lead sent by two tools counts twice. Send each lead one way only.
  • No journey for a lead whose tool did not carry the visitor ID, or while visitor IDs are off.
  • An outgoing message never holds a name or an email. A CRM matches it by the tool's reference it carries.
  • Outgoing webhooks send only what happens after you add them: no backfill out.
  • The Integrations page needs team accounts. On a one-login server, whoever runs it sets hooks up on the server.

questions

Analytics webhooks FAQ

Straight answers, including what Skald does not do.

Which tools can send webhooks to Skald?

Calendly, Cal.com, HubSpot, Typeform and Stripe each have their own signed hook. Zapier, Make, n8n and form plugins post to the json hook. Your own site's server posts to the lead hook, or uses a one-file helper for PHP, Node or Python, or the WordPress plugin.

How does Skald know a webhook is real?

Each hook has its own secret. Skald checks the message's signature with it before it keeps anything, and refuses a time more than 5 minutes off its own clock. No-code tools may send the secret as a plain key, Authorization: Bearer, on the json and lead hooks only. A wrong key is refused like a bad signature.

What happens when a tool sends the same webhook twice?

Nothing is counted twice. Skald keeps each conversion once per tool, reference and stage. A repeat is answered OK and shows as already had it in Last deliveries. Cal.com and Typeform sign no time, so Skald also remembers each of their messages for 30 days and ignores an exact repeat.

Can Skald send webhooks out?

Yes. Add an HTTPS address under Outgoing webhooks and tick the events: conversions by stage, abandoned starts, leads won or lost, AI reading changes and alert.opened. Each message is signed, and never holds a name or an email. Only events after you add the webhook are sent.

What does Skald keep from a webhook?

The action, its stage, the time, the tool and its own reference, the visitor ID when visitor IDs are on, and the source, campaign, landing page, country and device when known. IP addresses, browser strings, phone numbers, form answers and customer details are always dropped. Names and emails are kept only when the site's setting keeps them.

How do I test a webhook?

Press Send a test event in the tool's box. Skald signs a sample, checks it, reads it, then keeps nothing and counts nothing, and says what a real message would keep. To check the other tool's side, use its own test button and look at Last deliveries.

$ tail -f access.log | skald

See what AI does with your site. Free for 30 days.

No card. We set up hosted Skald for you within one working day, or you self-host it free. Every line of your log, sorted and added up.

Start free trial Live demo