Voyado
Datafly Signal syncs identified contacts to Voyado Engage server-to-server using the Engage Contacts API (v3). When a visitor identifies themselves — signs up, logs in, or submits a form — Signal creates or updates their Engage contact with their name, email, phone, locale, and marketing-consent preferences.
Voyado’s Engage API is server-side only — client-side calls are blocked by CORS. Signal delivers from your own infrastructure, so the API key never reaches the browser.
Why route Voyado through Datafly Signal
- Profiles are updated from the server, not the browser. Events reach Voyado even when a tracker blocker or a failed page unload would have dropped a client-side call, so the profile reflects what actually happened.
- One consent decision governs every destination. Voyado is gated by the same consent state as the rest of your stack, so a withdrawal applies everywhere at once.
Prerequisites
Before configuring Voyado in Signal, you need a Voyado Engage tenant and an API key.
Step 1: Find Your Tenant Name
Your tenant name is the first part of your Engage URL. If you sign in at https://acme.voyado.com, your tenant name is acme. Use the matching staging tenant (https://acme.staging.voyado.com → acme.staging) when testing against a staging environment.
Step 2: Create an API Key
- In Engage, go to Configure > API connections.
- Create a new API key. Voyado recommends a unique key per integration, so name it something identifiable (e.g. “Datafly Signal”).
- Copy the key — you will paste it into Signal.
The API key is sent in the apikey HTTP header. Never put it in a URL or expose it client-side.
Step 3: Confirm Your Contact Type
New contacts are created with a contact type. If you don’t specify one, Engage defaults to Member. If your instance uses a custom contact type for web sign-ups, note its exact name.
Configure in Signal
Configuration Fields
| Field | Required | Description |
|---|---|---|
tenant | Yes | Your Voyado tenant name (e.g. acme for https://acme.voyado.com). |
api_key | Yes | Engage API key from Configure > API connections. Sent in the apikey header. |
contact_type | No | Contact type for new contacts, sent as contactType in the body (and the query string). Voyado defaults to Member if blank. |
Management UI Setup
Add the integration
Go to Integrations > Add Integration > Voyado.
Enter your credentials
Fill in your tenant name and api_key, and optionally a contact_type.
Select consent categories
Choose the consent categories that gate delivery. Cookie consent is not mapped to Voyado’s acceptsEmail, acceptsSms or acceptsPostal: those are communications preferences, which a cookie banner must never set.
Save
Click Save. The integration is now live.
API Endpoint
POST https://{tenant}.voyado.com/api/v3/contacts?contactType={contact_type}&source=datafly-signalAuthentication is the apikey request header. Each request also sends User-Agent: Datafly-Signal/1.0 and Content-Type: application/json, both required by Engage.
POST /api/v3/contacts only creates. For a contact that already exists, Voyado answers 409 Conflict (ApprovedContactWithKeyExists); Signal treats it as permanent and does not retry. Updating an existing contact needs Voyado’s lookup-then-PATCH flow, which Signal cannot run yet (#1490).
Identity Signals
Voyado is a first-party CRM and stores raw contact details — it does not accept hashed match keys. Signal sends these fields in plaintext to your own Voyado instance:
| Signal trait | Voyado field | Notes |
|---|---|---|
email | email | Lowercased and trimmed. Primary unique identifier. |
phone | mobilePhone | Normalised to E.164. Paired with countryCode. |
first_name | firstName | |
last_name | lastName | |
country | countryCode | ISO country code, upper-cased; Engage auto-populates the country name. |
context.locale | lang | For example en-GB. |
user_id | externalId | Your own stable customer ID, stored as Engage externalId. |
The preset keys contacts on email: identity events without an email are not delivered.
How to Send Contact Data
Call datafly.identify() when a user signs up, logs in, or submits a form:
datafly.identify("user-123", {
email: "jane.doe@example.com",
phone: "+46 70 123 45 67",
first_name: "Jane",
last_name: "Doe",
country: "SE"
});Event Mapping
The Voyado Contacts API accepts profile data, not behavioural events. Signal therefore delivers only identity-bearing events to Voyado; all other events (page views, product views, purchases) are dropped because they carry no contact identifier.
Default preset
| Signal event | Voyado action |
|---|---|
sign_up | Create contact |
identify | Create contact |
Example: Sign-up
Datafly.js call:
datafly.track("sign_up", { method: "email" });
// ...with traits previously set via datafly.identify():
datafly.identify("user-123", {
email: "jane.doe@example.com",
phone: "+46 70 123 45 67",
first_name: "Jane",
last_name: "Doe",
country: "SE"
});Voyado payload sent by Signal:
{
"email": "jane.doe@example.com",
"firstName": "Jane",
"lastName": "Doe",
"mobilePhone": "+46701234567",
"countryCode": "SE",
"lang": "sv-SE",
"externalId": "user-123",
"contactType": "Member"
}A successful create returns HTTP 201 Created with the full contact record.
Testing
Use your staging tenant
Point the tenant field at your staging tenant (e.g. acme.staging) so test contacts don’t land in production.
Trigger an identify
Sign up or log in on your site, or fire datafly.identify() from the browser console with a test email.
Verify in Engage
In Engage, search Contacts for the test email. The contact should appear with the name and phone you sent. Re-running the same identify returns 409 (the contact exists) and changes nothing.
Troubleshooting
| Problem | Solution |
|---|---|
401 / 403 responses | The apikey is wrong, revoked, or lacks contact permissions. Regenerate it under Configure > API connections. |
404 responses | The tenant name is wrong. Check the first part of your Engage URL and whether you should be using a staging tenant. |
400 responses | The contact is missing a unique identifier — ensure email or phone is set via datafly.identify(). |
| Contact not appearing | Confirm the event is sign_up or identify and that traits include an email. Other events are dropped by design. |
409 responses | The contact already exists; the endpoint only creates (#1490). |
| Wrong contact type | Set the contact_type field to a type that exists in your Engage instance. |