Delivered without slowing clicks
The visitor click is served first. Webhook delivery is logged and processed in the background.
Tip: routing rules run before the classic split, then fallback takes over.
Developer beta
Send clicks, matched routing rules and short-link events to internal tools, Make, Zapier, a CRM or a reporting stack. Visitor redirects stay first: webhooks are delivered in the background.
Beta status: the UI, signature and retries are operational. Events and fields may still evolve before full stabilization; verify your integrations after each new event type.
The visitor click is served first. Webhook delivery is logged and processed in the background.
Each POST includes an HMAC SHA-256 signature in X-Linka-Factory-Signature.
Network errors and non-2xx HTTP responses are retried automatically, with a visible log in Settings.
campaign.click.recordedA click was served by a campaign.
campaign.routing_rule.matchedAn advanced routing rule was applied before distribution.
short_link.click.recordedA click was served by a Linka Factory short link.
{
"id": "evt_campaign_click_recorded_01hq...",
"type": "campaign.click.recorded",
"created_at": "2026-05-01T17:40:00.000Z",
"account_id": "acc_...",
"data": {
"accountId": "acc_...",
"timestamp": "2026-05-01T17:40:00.000Z",
"campaignId": "cmp_...",
"urlId": "url_...",
"servedUrl": "https://example.com/landing-a",
"routingRuleId": "rule_...",
"routingRuleLabel": "France mobile",
"country": "FR",
"deviceType": "mobile",
"browserFamily": "chrome",
"platformFamily": "android",
"sourceSite": "newsletter",
"refererHost": "example.com",
"ipMasked": "203.0.113.0",
"suspicious": false
}
}The signature is computed from timestamp dot raw body. Keep the exact received body before JSON parsing.
import crypto from "node:crypto"
export function verifyLinkaFactoryWebhook({ rawBody, signatureHeader, secret }) {
const parts = Object.fromEntries(
signatureHeader.split(",").map((part) => part.split("=").map((value) => value.trim()))
)
const timestamp = parts.t
const expected = crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("hex")
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(parts.v1 || "", "hex")
)
}Delivery
An HTTP 2xx status marks the delivery as sent. Other statuses, timeouts and network errors move to retry.
The current schedule retries roughly after 60 seconds, 5 minutes, 30 minutes, then 2 hours, with up to 5 attempts.
The latest deliveries log shows status, attempt count, HTTP code and a response preview for quick debugging.
Next step