Salesforce Developer
This guide covers what you need to know as a developer implementing an io.tt experience that routes participant data into Salesforce. It explains the field mapping, type constraints, and how to pass custom fields.
For instructions on connecting Salesforce to io.tt in the dashboard, see the Salesforce Setup Guide (for brand admins).
For a general overview of CRM routing across all integrations, see the CRM Integration Guide.
How It Works (From Your Perspective)
No Salesforce-specific code is required in your experience. Call the standard signup method for your experience type — the platform handles field mapping and writing to Salesforce server-side:
import { IOTT } from "@io-tt/sdk";
const sdk = new IOTT({ apiKey: process.env.IOTT_API_KEY });
await sdk.signupForCompetition(EXPERIENCE_ID, {
uid: userEmail,
email: userEmail,
firstName: "Jane",
lastName: "Smith",
marketingConsent: true,
extra: {
ageRange: "25-34",
productPreference: "single-malt",
},
});The fields you pass map directly to Salesforce standard and custom fields. io.tt applies the transformer server-side; you do not configure this in code.
Standard Field Mapping
These io.tt fields map to standard Salesforce fields on the Lead or Contact object. The Type column reflects what the SDK expects from your code — Salesforce field length limits are noted where they constrain what you collect.
| io.tt field | Salesforce field | Type | Format / Constraints |
|---|---|---|---|
firstName | FirstName | string | Max 40 chars |
lastName | LastName | string | Required by Salesforce; io.tt defaults to "Unknown" if omitted. Max 80 chars |
email | Email | string | Must be a valid email address. Primary upsert key. Max 80 chars |
phoneNumber | Phone | { countryCode: number; number: string } | Sent to Salesforce as +{countryCode}{number}. Max 40 chars combined |
dateOfBirth | Birthdate | string | ISO 8601 date: YYYY-MM-DD. Contact only — not mapped on Lead |
title | Salutation | string | Salesforce picklist — value must match exactly (case-sensitive): Mr. Ms. Mrs. Dr. Prof. — including the full stop. Values outside this list will be rejected by Salesforce. |
addressLine1 | Street / MailingStreet | string | Lead uses Street; Contact uses MailingStreet. Max 255 chars |
locality | City / MailingCity | string | Max 40 chars |
administrativeDivision | State / MailingState | string | Max 80 chars |
postalCode | PostalCode / MailingPostalCode | string | Max 20 chars |
country | Country / MailingCountry | string | ISO 3166-1 alpha-2 recommended (e.g. "GB"). Max 80 chars |
marketingConsent | HasOptedOutOfEmail | boolean | Inverted: true → HasOptedOutOfEmail: false. Always pass explicitly if your form collects this |
io.tt Context Fields (Custom)
These are written to custom fields the brand's Salesforce administrator creates once. They allow segmentation by experience within Salesforce. You do not set these manually — io.tt populates them automatically from the experience context.
| Salesforce custom field | Type | Value source |
|---|---|---|
io_tt_participant_id__c | Text(255) | io.tt participant ID |
io_tt_experience_id__c | Text(255) | Experience ID |
io_tt_experience_name__c | Text(255) | Experience name (set in dashboard) |
io_tt_experience_type__c | Text(50) | authentication / competition / loyalty / gifting / golden_ticket |
io_tt_brand_name__c | Text(255) | Brand name (set in dashboard) |
io_tt_extra_{key}__c | Text | One per extra key — see below |
Custom Fields via extra
All signup methods accept an extra object for any data your form collects beyond the standard fields. Each key maps to a io_tt_extra_{key}__c custom field in Salesforce:
await sdk.signupForCompetition(EXPERIENCE_ID, {
uid: userEmail,
email: userEmail,
marketingConsent: true,
extra: {
ageRange: "25-34", // → io_tt_extra_agerange__c
productPreference: "whisky", // → io_tt_extra_productpreference__c
retailer: "harrods-london", // → io_tt_extra_retailer__c
},
});Constraints for extra fields:
- Values must be
stringor primitive — nested objects are not supported for CRM mapping - Keys are lowercased when mapped to Salesforce field names
- The corresponding
io_tt_extra_{key}__ccustom field must exist in Salesforce before data will appear — coordinate field names with the brand's Salesforce administrator before launch
Upsert Behaviour
io.tt uses upsert when writing to Salesforce — meaning if a record with the same email already exists, it is updated; if not, a new one is created. This means the same person registering multiple times — or across different experiences — will never result in duplicate Salesforce records.
The match is done on Email by default. If your experience uses a non-email uid (e.g. a loyalty card number), discuss this with your io.tt account manager — the upsert field can be changed to a custom io_tt_uid__c field.
Object Type
io.tt writes to either Lead or Contact — configured per experience in the io.tt dashboard. This affects field names (e.g. Street vs MailingStreet) and which fields are available (Birthdate is Contact-only). Check with your io.tt account manager which object type your experience uses before building your form.
Notes
- CRM routing is configured by io.tt staff — you do not specify the Salesforce target in code.
dateOfBirthis only mapped on Contact objects. If the experience uses Lead, omit this field from your form or store it inextra.- All field mapping and transformation is applied server-side. Treat SDK responses as the source of truth — the SDK does not validate field values against Salesforce constraints before submission.
- Coordinate
extrafield keys with the brand's Salesforce administrator before launch to ensure matching custom fields exist.