-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Summary
When using JWT authentication, calling trackInAppOpen, trackInAppDelivery, trackInAppClick, or trackInAppConsume always results in a 400 Bad Request: "Either email or userId must be specified". trackInAppClose works correctly.
SDK Version
@iterable/web-sdk@2.2.1
Root Cause
Two behaviours in the SDK interact to create an impossible state:
Step 1 — dist/events/inapp/events.js:26-27 deletes email and userId from the payload before the request is sent:
delete payload.userId;
delete payload.email;
Step 2 — The axios interceptor in dist/authorization/authorization.js re-adds email to POST requests, but explicitly excludes these 4 routes:
&& !(config?.url?.includes('/events/trackInAppDelivery'))
&& !(config?.url?.includes('/events/trackInAppClick'))
&& !(config?.url?.includes('/events/trackInAppOpen'))
&& !(config?.url?.includes('/events/inAppConsume'))
The result: email is stripped in step 1, and the interceptor is blocked from re-adding it in step 2. The Iterable API requires email in the body — there is no way to satisfy this through the SDK's public API.
trackInAppClose works by accident — it was left out of the exclusion list.
Workaround
Bypass the SDK's track functions and call the Iterable API directly via fetch, explicitly including email in the body:
await fetch(https://api.eu.iterable.com/api/events/trackInAppOpen, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Api-Key": ITERABLE_PUBLIC_KEY,
"Authorization": Bearer ${jwt},
},
body: JSON.stringify({ email, messageId }),
});
Expected Behaviour
trackInApp* functions should include email or userId in the request body, consistent with how trackInAppClose works and what the Iterable API requires.