Salesloft
Salesloft is a sales engagement platform. This integration lets Datafly Signal create or update a Person in Salesloft whenever a visitor identifies or converts on your site, so inbound web leads land in your sales workflow server-side, without a browser-side script and without losing leads to ad-blockers or consent gates.
Signal delivers to the Salesloft Person Upsert API: one server-to-server POST per qualifying event. The upsert is keyed on email address, so resubmitting the same lead updates the existing Person instead of creating a duplicate.
Prerequisites
- A Salesloft account with permission to create and update People.
- A Salesloft API key with the People scope. In Salesloft, go to Your Applications > API Keys > Create New, give it a descriptive name, select the People scope, and copy the key (shown only once).
- A Datafly Signal pipeline already collecting events from your site via Datafly.js.
Configuration
| Field | Required | Description |
|---|---|---|
| API Key | Yes | Your Salesloft API key with the People scope, from Your Applications > API Keys. Stored encrypted; sent as the Authorization: Bearer header on every request. |
Configure in Signal
- In the Management UI, open your pipeline and choose Add integration > Salesloft.
- Paste your API Key.
- Select the Lead Capture preset. It maps
Lead Generated,Signed Up, andIdentifiedevents to a Salesloft Person upsert; all other events are dropped. - Save. Signal validates the credential on the first qualifying event; a
200with a Personidin the response confirms the integration is live.
API Endpoint
POST https://api.salesloft.com/v2/person_upserts
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonA successful upsert returns 200 with the created or updated Person:
{ "data": { "id": 1234, "email_address": "jane.doe@example.com" } }Identity Signals
Salesloft is a first-party CRM that you own and use to contact leads, so contact details are stored as plaintext (unlike advertising integrations, which hash PII). Signal sends:
| Signal source | Salesloft field | Notes |
|---|---|---|
traits.email | email_address | Trimmed and lower-cased. Used as the upsert_key, so it also matches existing People. |
traits.first_name | first_name | |
traits.last_name | last_name | |
traits.phone | phone | Normalised to E.164. |
traits.title | title | Job title. |
traits.company | person_company_name |
Consent is honoured: when the visitor’s canonical marketing consent is granted, Signal sends do_not_contact: false; when consent is denied or absent it sends do_not_contact: true, so leads who haven’t opted in are flagged not-to-contact in Salesloft.
Campaign attribution is written to custom_fields (utm_source, utm_medium, utm_campaign, signal_landing_page) and the event’s lead source is added to tags. Salesloft rejects custom_fields keys that don’t already exist as Person custom fields, so create those custom fields in your tenant first (or remove the mappings if you don’t need them).
Event Mapping
| Datafly.js event | Salesloft action |
|---|---|
Lead Generated | Upsert Person (adds lead_source to tags) |
Signed Up | Upsert Person (records signup method) |
Identified | Upsert Person |
| (everything else) | Dropped |
Example
When a visitor submits a contact form, fire a Lead Generated event with identity traits:
datafly.track("Lead Generated", {
lead_source: "Website Contact Form"
}, {
traits: {
first_name: "Jane",
last_name: "Doe",
email: "Jane.Doe@Example.com ",
phone: "07700 900123",
title: "Head of Marketing",
company: "Example Ltd"
}
});Signal transforms and delivers this to Salesloft as:
{
"upsert_key": "email_address",
"email_address": "jane.doe@example.com",
"first_name": "Jane",
"last_name": "Doe",
"phone": "+447700900123",
"title": "Head of Marketing",
"person_company_name": "Example Ltd",
"do_not_contact": false,
"tags": ["Website Contact Form"],
"custom_fields": {
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "brand"
}
}Note the email was trimmed and lower-cased and the phone normalised to E.164 before delivery, and do_not_contact is false because marketing consent was granted.
Testing
- Submit a test form on your site (or fire
datafly.track("Lead Generated", ...)from the browser console) with a real name and email. - In Salesloft, open People and confirm the new Person appears with the correct email, phone and company.
- Resubmit the same email with a changed field (e.g. a new title) and confirm Salesloft updates the existing Person rather than creating a duplicate.
- In the Signal Event Debugger, confirm the event delivered with a
200and a Personidin the response body.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
401 Unauthorized | Invalid or revoked API key | Re-create the key in Your Applications > API Keys and update the integration. |
403 Forbidden | API key missing the People scope | Re-create the key with the People scope selected. |
400 / 422 referencing a custom field | A custom_fields key doesn’t exist in your tenant | Create the matching Person custom field in Salesloft, or remove that mapping from the preset. |
400 Bad Request missing email | Event has no traits.email | Pass traits.email in the event’s identity context; it’s required as the upsert key. |
| Duplicate People created | upsert_key not sent, or different email casing | The preset sends upsert_key: email_address and lower-cases email; confirm you haven’t overridden these. |
429 Too Many Requests | Team-level rate limit hit | Salesloft rate-limits per team across all integrations; Signal retries automatically, but reduce volume or stagger if persistent. |