Send webhook automation
The Send webhook automation posts the visitor's profile as JSON to a URL you choose when they interact with a widget element. Use it to send leads to your own backend, Zapier, Make or any tool that accepts webhooks.
Available on: all platforms.
How it works
- You add Send webhook to an element and enter the URL.
- When the element's event happens, the event is recorded on Personizely's servers, and the visitor's profile is updated with anything they just submitted.
- Personizely's servers send a POST request to your URL with a JSON body describing the event, the widget and the visitor's full profile.
The webhook is sent for these events:
event | When |
|---|---|
click | A Button, Image or Products button is clicked |
submit | A Form or Survey is submitted |
succeed | A Countdown timer reaches zero, or Cart progress reaches its goal, while the widget is displayed |
spin | A Wheel of fortune lands on a segment that has this automation |
Configuration
Option | What it does | Values / default |
|---|---|---|
URL | Where the request is sent | A valid http or https URL; required |
Request
- Method POST, header Content-Type: application/json.
- Personizely waits up to 3 seconds to connect and up to 30 seconds for your response.
- If your endpoint can't be reached, times out or answers with a 5xx error, the request is retried up to 2 more times (3 attempts in total), with a growing delay. A 429 response is retried after its Retry-After delay. Other 4xx responses aren't retried. Retries mean the same event can arrive more than once.
Payload
The body contains the current fields (event, widget, visitor) and, for older integrations, two legacy fields (widgetId, visitorData) with the same information. Build new integrations on widget and visitor.
{
"event": "submit",
"widgetId": 8812,
"visitorData": {
"email": "[email protected]",
"firstName": "Jane",
"lastName": null,
"companyName": null,
"companyTitle": null,
"phone": "+14155550123",
"address": null,
"marketingConsent": null,
"emailMarketingConsent": true,
"smsMarketingConsent": null,
"privacyConsent": true,
"birthdate": null,
"bio": null,
"utmSource": "instagram",
"utmCampaign": "summer_sale",
"utmContent": null,
"utmTerm": null,
"utmMedium": "social",
"firstVisitPage": "/products/linen-shirt",
"referrer": "https://l.instagram.com/",
"country": "US",
"city": "San Francisco",
"region": "California",
"zipCode": "94103",
"41": "Gift",
"57": null,
"firstVisit": "2026-10-02T14:03:12+0000",
"lastVisit": "2026-10-16T09:41:55+0000"
},
"widget": {
"id": 8812,
"name": "Summer newsletter popup",
"type": "popup"
},
"visitor": {
"firstVisit": "2026-10-02T14:03:12+0000",
"lastVisit": "2026-10-16T09:41:55+0000",
"email": "[email protected]",
"firstName": "Jane",
"lastName": null,
"companyName": null,
"companyTitle": null,
"phone": "+14155550123",
"address": null,
"marketingConsent": null,
"emailMarketingConsent": true,
"smsMarketingConsent": null,
"privacyConsent": true,
"birthdate": null,
"bio": null,
"utmSource": "instagram",
"utmCampaign": "summer_sale",
"utmContent": null,
"utmTerm": null,
"utmMedium": "social",
"firstVisitPage": "/products/linen-shirt",
"referrer": "https://l.instagram.com/",
"country": "US",
"city": "San Francisco",
"region": "California",
"zipCode": "94103",
"customFieldValues": {
"41": "Gift",
"57": null
}
}
}Field reference
Field | Type | Description |
|---|---|---|
event | string | click, submit, succeed or spin |
widget.id | number | Widget ID |
widget.name | string | Widget name as shown in Personizely |
widget.type | string | popup, callout, bar or embedded |
visitor.firstVisit, visitor.lastVisit | string | ISO 8601 date and time of the visitor's first and latest visit, e.g. 2026-10-16T09:41:55+0000 |
visitor.email, firstName, lastName, companyName, companyTitle, phone, address, bio | string or null | Profile fields. phone is normalized to + and digits when collected by a Personizely form |
visitor.marketingConsent | true or null | true only when both email and SMS marketing consent are given |
visitor.emailMarketingConsent, smsMarketingConsent, privacyConsent | true or null | Consent checkboxes |
visitor.birthdate | object or null | Date of birth, when collected |
visitor.utmSource, utmCampaign, utmContent, utmTerm, utmMedium | string or null | The visitor's stored UTM values |
visitor.firstVisitPage | string or null | Path of the first page the visitor ever viewed |
visitor.referrer | string or null | The referrer stored on the visitor's profile |
visitor.country | string or null | Two-letter country code |
visitor.city, region, zipCode | string or null | Location from the visitor's IP. region is the region's name |
visitor.customFieldValues | object | Every custom field, keyed by its numeric ID, null when not set |
widgetId | number | Legacy: same as widget.id |
visitorData | object | Legacy: the profile fields plus firstVisit and lastVisit, with custom fields at the top level keyed by ID |
Behavior details and limitations
- It's the whole profile, not just this form. The payload contains everything stored on the visitor, including values from earlier forms. Fields a form didn't collect can still have values.
- Empty values are null. Unset fields, empty text and unchecked consent checkboxes are all sent as null, never false or "".
- What's not included. The payload has no visitor ID, event timestamp, page URL or wheel segment. Use Execute JavaScript code or a Change field value automation to add data you need.
- Protect your endpoint. Put a hard-to-guess token in the webhook URL, such as https://hooks.example.com/ply?token=8f3k..., and reject requests without it.
- Make your endpoint idempotent. Retries and repeat submissions can deliver the same lead more than once. Deduplicate on visitor.email or visitor.phone.
- Respond fast. Answer with a 2xx status as soon as you've received the data, and do slow work afterwards.
- No webhooks in preview or for the control group. Preview records no events, and control-group visitors see nothing.
Examples
- Leads to your CRM: Form with Send webhook to your backend, which creates the contact and returns 200.
- Zapier: Send webhook to a Zapier "Catch Hook" URL, then map visitor.email and visitor.customFieldValues.41 to your tools.
Troubleshooting
- Nothing arrives → the URL isn't reachable from the internet, the element's event wasn't recorded, or you're testing in preview.
- Duplicate deliveries → your endpoint took longer than 30 seconds or returned a 5xx error, so the request was retried.
- A custom field is missing a name → custom fields are keyed by ID. Look up each custom field's ID in Personizely and map it in your endpoint.