SendGrid
SendGrid (Twilio SendGrid) is an email delivery and marketing platform. This destination syncs your Jitsu users to SendGrid as marketing contacts and manages their list membership, using the Marketing Contacts API.
How it works
SendGrid identifies contacts by email address. Jitsu maps events to SendGrid contacts as follows:
| Event | What Jitsu does |
|---|---|
identify | Upserts the contact (create or update) and reconciles its list membership. |
track / page / screen | Updates the existing contact's fields (never creates a contact). |
group | Updates the existing contact with the group id and group traits as group_* fields. |
Contact upserts in SendGrid are asynchronous — the API accepts the request (HTTP 202) and processes it in the background, so changes may take a moment to appear in the dashboard.
identify
Each identify() upserts a contact via PUT /v3/marketing/contacts:
- Email is read from
traits.email(falling back tocontext.traits.email). Events without an email are skipped. - First / last name come from
traits.firstName/traits.lastName, or are split fromtraits.name. - The Jitsu
userIdandanonymousIdare stored as the custom fieldsjitsu_user_idandjitsu_anonymous_id. (Email is kept as the contact's only SendGrid identifier — SendGrid rejects an upsert that omits any identifier a matched contact already has, souserId/anonymousIdare not used as SendGrid identifiers.) - All other traits are stored as SendGrid
custom fields. SendGrid requires custom
fields to be defined before use and references them by an internal field ID, so Jitsu automatically creates a
Textfield definition for each new trait key it sees and maps values to the right IDs. Traits whose names match a writable SendGrid reserved field (city,country,postal_code, …) are written to that reserved field instead. - The contact's list membership is reconciled to match the configured set.
A repeated identify() for the same email updates the existing contact rather than creating a duplicate.
Other events
track, page, screen and group events update an existing contact but never create one. Because the
SendGrid upsert would otherwise create a contact, Jitsu first checks that the contact exists (via the
search API) and skips
the event if it doesn't. An update happens only when the event carries fields explicitly set on it (typically
added by a transformation function) — ambient identify traits echoed on the event are
ignored so the contact isn't rewritten on every event.
Lists
Set Lists in the destination config to a comma-separated list of list names (not IDs) — for example
Customers, Beta. Jitsu resolves each name to a SendGrid Marketing list, creating any that don't exist yet.
Leave it empty to add contacts without a list.
You can override the lists per event by setting a sendgridLists trait (also comma-separated names) from a
function:
export default async function (event) {
if (event.traits?.plan === "enterprise") {
event.traits.sendgridLists = "Customers, Enterprise";
}
return event;
}Membership is reconciled
On each identify(), Jitsu makes the contact's membership match the desired set. Lists it previously added
that are no longer listed are removed. For example, if a function returns A, B on one event and B, C on
the next, the contact is removed from A, kept in B, and added to C.
To do this safely, the connector records which lists it added in a custom field named jitsu_managed_lists — so
it only ever removes lists it added, never ones you added manually or via another tool. There's no separate
state stored in Jitsu; the record lives on the contact.
Notes:
- Reconciliation runs only when a desired set is provided for the event — i.e. the
sendgridListstrait is present, or the destination has configured Lists. An event with neither leaves membership untouched. - Setting
sendgridListsto an empty string explicitly clears the connector-managed lists. - Only
identify()manages membership;track/page/groupevents never change it.
Matching events by userId
SendGrid matches contacts by email. Enable Resolve email from userId to have every identify() cache a
userId → email mapping, so later track / page / group events that carry only a userId can be matched to
the contact via that cache. The cache is only populated from identify() calls seen after the flag is enabled.
If neither an email nor a cached userId resolves, the event is skipped.
Notes
- Unsubscribe / suppression state is managed separately in SendGrid (suppression groups) and is not set by this destination.
- Contact upserts are processed asynchronously by SendGrid and can take up to a minute or two to appear. The first event that introduces a brand-new custom field is retried once (a just-created field definition isn't usable immediately); it lands automatically on the retry.
- SendGrid's free tier is a time-limited trial; a paid Marketing Campaigns plan is required for ongoing use.