Iterable Migration Guide
Upgrading to 1.0.0
This version introduces a breaking change to the users stream schema.
What changed
-
Custom fields moved to
dataobject: Tenant-specific custom data fields are no longer top-level properties. They are now nested inside a genericdataobject, similar to how theeventsstream handles custom event data. The following 52 previously declared top-level properties move underdata:accepts_marketing,address1,addresses,admin_graphql_api_id,aov,boughtSas,businessLines,default_address,emailAcquiredDate,emailSegmentStatus,firstCampaign,firstMedium,firstName,firstOrderCards,firstOrderDate,firstPurchaseDate,firstSource,first_name,hasAccount,hasReminder,id,lastInteractionTs,lastName,last_name,last_order_id,last_order_name,ltr,mostRecentCampaign,mostRecentEmailList,mostRecentEmailSegment,mostRecentMedium,mostRecentOrderCards,mostRecentOrderDate,mostRecentSource,orders_count,secondMostRecentOrderCards,secondMostRecentOrderDate,secondOrderCards,secondOrderDate,shopify_created_at,shopify_updated_at,state,tax_exempt,thirdMostRecentOrderCards,thirdMostRecentOrderDate,thirdOrderCards,thirdOrderDate,totalOrders,total_spent,twelveMonthLtr,verified_email,zipAny other custom field your Iterable project defines (previously dropped because it was not declared) now also arrives inside
data. -
itblInternalflattened to dotted keys: TheitblInternalfield was previously declared as a nested object. The Iterable export API actually returns Iterable-internal fields as flat dotted keys (e.g.itblInternal.emailDomain,itblInternal.isUnknownUser). The schema now declares these dotted keys directly; Iterable-internal dotted keys that are not declared in the schema are captured in thedataobject. Note that most destinations transform unsupported characters in column names, so a field likeitblInternal.emailDomaintypically lands as a column nameditblinternal_emaildomain(exact form depends on the destination's name transformer). -
Timestamp values normalized to RFC3339: the Iterable export API returns
signupDate,itblInternal.documentCreatedAt, anditblInternal.documentUpdatedAtas space-separated timestamps (e.g.2024-01-15 10:30:00 +00:00), which typed destinations could not parse astimestamp_with_timezoneand nulled into_airbyte_meta.changes. The connector now emits these fields in RFC3339 format (2024-01-15T10:30:00+00:00), matching the declaredformat: date-time.profileUpdatedAtalready arrives in RFC3339 from the API and is unchanged in practice (it passes through the same normalization defensively). -
Added standard fields:
itblUserId,whatsAppPhoneNumber,city, andregion- documented Iterable-managed fields - are now declared in the schema.
Migration steps
- Refresh the source schema for the
usersstream in your connection settings, so the newdataobject and dotted-key columns appear. - If you have downstream transformations that reference any of the moved top-level fields listed above, update them to read from the
dataobject instead (e.g.data.addresses,data.aov,data.firstName). - If you reference
itblInternal.emailDomainor similar fields, note that they are now top-level dotted-key fields rather than nested under anitblInternalobject, and your destination may transform the.in the column name. - If you have transformations that parse
signupDate, note that its values are now RFC3339 (Tseparator, no space before the offset).
Clearing the stream is optional
The users stream has no primary key and syncs in append mode, so no deduplication depends on this change and a clear is not required for correctness. Without a clear, rows synced before the upgrade keep the old shape (custom fields as top-level columns) next to new rows that carry them inside data - your history stays intact, and only the new rows follow the new structure.
Clear the stream only if you want the whole table rebuilt in the new shape, and be aware of the trade-off: the users stream syncs incrementally by profileUpdatedAt starting from your configured start date, so a backfill after a clear only re-syncs profiles updated after that date. Profiles that have not been updated since then are not re-exported by Iterable and would be lost from the destination. Snapshot or copy the destination table before clearing if you need that history.