Summarize this documentation using AI
Overview
If you’re upgrading your Flutter app instrumentation for Customer.io, treat the 2.x jump like a retention reliability project—not a routine dependency bump. Most D2C teams only notice tracking issues after revenue-critical automations (cart recovery, replenishment nudges, winback) quietly stop triggering or start attributing to the wrong person.
If you want a second set of eyes on identity stitching, event parity, and “did we break journeys?” validation, you can book a strategy call and we’ll walk through the upgrade plan the same way we would for a high-volume store.
How It Works
In practice, the Flutter 2.x upgrade matters because it changes how your app-side SDK initializes, identifies users, and sends events/devices into Customer.io. Your retention engine depends on three things being consistent before and after the upgrade: (1) the same person gets the same identifier, (2) the same events fire with the same names/properties, and (3) the same device/push token stays attached to the right profile.
- SDK initialization: your app boots the SDK with site/workspace credentials and environment-specific settings. If initialization becomes conditional (only after login, only on certain routes), you’ll see missing anonymous activity and fewer recoveries from browse/cart flows.
- Identity stitching (anonymous → known): a user often browses and adds to cart before logging in. The upgrade is “successful” only if you still merge that pre-login activity into the post-login profile via a consistent identify call at the right moment.
- Event tracking parity: retention automations usually key off a small set of events (e.g.,
Added to Cart,Checkout Started,Order Completed). If event names or required properties drift during the upgrade, campaigns won’t trigger or segmentation will fragment. - Device management: push is especially sensitive. If tokens stop updating, or get associated with duplicate profiles, you’ll see push deliverability drop and “wrong person got the message” edge cases.
Real D2C scenario: A shopper adds a moisturizer to cart while anonymous, then logs in at checkout. Your cart recovery journey relies on the Added to Cart event and a 2-hour delay. If your 2.x upgrade stops merging anonymous activity, the cart journey either never triggers (no event on the known profile) or triggers on an anonymous profile that can’t receive email/SMS—both look like “cart recovery stopped working.”
Step-by-Step Setup
The cleanest way to upgrade is to protect production tracking first, then validate parity in a staging workspace (or a controlled production rollout). Don’t start by editing journeys—start by proving the SDK still produces the same people and events.
- Inventory your current tracking contract
- List the exact event names your retention flows depend on (cart, checkout, purchase, product viewed, subscription started, etc.).
- Capture required properties (e.g.,
product_id,sku,price,currency,cart_id,order_id). - Document your identity rules: what you use as
customer_id(recommended) vs email, and when you call identify (app launch vs login vs both).
- Upgrade the Flutter SDK dependency to 2.x
- Update your
pubspec.yamlto the 2.x package version per Customer.io’s Flutter SDK upgrade notes. - Re-run build steps for iOS/Android (pods/gradle) and confirm the app compiles cleanly.
- Update your
- Re-validate SDK initialization timing
- Initialize as early as practical (typically app start), not only after login—otherwise you lose anonymous browse/cart signals.
- Confirm environment config (prod vs staging) so you don’t pollute production data during QA.
- Implement (or re-confirm) identify on login
- On successful authentication, call identify with a stable identifier (ideally your internal customer ID).
- Set core attributes at identify time (email, phone, first_name, marketing opt-in flags) so downstream messaging has what it needs.
- If your pre-login experience tracks events, confirm anonymous activity merges into the identified profile after login.
- Re-implement event tracking with exact parity
- Keep event names identical unless you’re intentionally migrating journeys/segments.
- Send the same properties with the same types (string vs number). Type drift is a common “segment suddenly empty” failure.
- Fire events at the same lifecycle moment (e.g.,
Checkout Startedwhen payment begins—not when the cart drawer opens).
- Validate push token/device behavior (if you use push)
- Confirm tokens register after permission grant and update on refresh.
- Confirm the token attaches to the identified profile after login (not stuck on an anonymous/duplicate profile).
- Run a parity QA script in staging
- Create a test user and run: app open → browse → add to cart → begin checkout → login → purchase.
- In Customer.io, verify: one person profile, correct identifiers, all events present, and event timestamps in the expected order.
- Roll out safely
- Use a phased release (percentage rollout) so you can catch identity/event issues before they hit your whole buyer base.
- Watch “events per day” and key trigger volumes (cart abandonment entries, purchase confirmations) during rollout.
When Should You Use This Feature
You don’t upgrade to 2.x because it’s “nice to have.” You do it when the upgrade removes tracking risk, unlocks newer SDK behavior, or fixes reliability issues that directly impact revenue flows.
- Cart recovery is undercounting: you see lots of add-to-cart behavior in analytics, but Customer.io journeys have low entry volume—often an identity merge or event timing issue that a clean SDK upgrade/rewire fixes.
- Repeat purchase flows need better accuracy: replenishment and cross-sell journeys depend on clean
Order Completedevents and consistent product metadata. - Reactivation depends on app-side signals: if you use “last app open” or “viewed product but didn’t buy,” you need the SDK to initialize early and track reliably even before login.
- You’re seeing duplicate profiles: most retention programs we’ve seen run into this when identify happens inconsistently across app versions—upgrading is a good forcing function to standardize identity.
Operational Considerations
The upgrade itself is engineering work, but the operational risk sits with retention: segmentation drift, broken orchestration, and messy identity graphs. Plan for the data reality, not the happy path.
- Segmentation stability: if you change event names/properties during the upgrade, you’ll need dual-tracking or segment rewrites. Otherwise, your “Added to Cart in last 4 hours” segment will split across two schemas.
- Data flow ordering: make sure identify happens before events that require a known user for messaging (email/SMS). If
Checkout Startedfires before identify, your triggered flows may attach to an anonymous profile. - Orchestration across channels: if you orchestrate push → email → SMS, device/push token correctness becomes a gating dependency. A token stuck on a duplicate profile will make your multi-step journey look “randomly broken.”
- Source of truth for purchases: for many D2C brands, purchase events come from backend/webhook sources, not the app. If you also track app-side purchase events, ensure you aren’t double-firing
Order Completedand inflating LTV segments.
Implementation Checklist
Before you call the upgrade “done,” you want proof that your revenue journeys will behave the same (or better) with 2.x in the wild.
- SDK 2.x installed and app builds cleanly on iOS + Android
- Initialization runs reliably on app start (not gated behind login)
- Identify called on login with stable
customer_id(and email/phone attributes set) - Anonymous pre-login events merge into the identified profile
- Event names match your existing “tracking contract” exactly
- Event property types match (no string/number flips)
- Push token registers and attaches to the correct identified profile (if using push)
- Staging QA script completed: browse → cart → checkout → login → purchase
- Production rollout monitored: trigger volumes and profile duplication checked
Expert Implementation Tips
The difference between a clean upgrade and a retention incident usually comes down to identity hygiene and event discipline.
- Standardize on one primary identifier: use your internal customer ID as the canonical ID and treat email as an attribute that can change. This reduces duplicate profiles when shoppers use Apple Hide My Email or change addresses.
- Track cart state with a stable cart ID: for cart recovery, include
cart_idand line items. When a shopper edits the cart, you can update the same cart context instead of creating noisy, unjoinable events. - Guard against double-fires: Flutter route rebuilds and state changes can accidentally fire “Viewed Product” multiple times. Put event dispatch behind clear user actions (or debounce) so segments don’t over-include high-frequency browsers.
- Validate with Customer.io activity logs, not just app logs: app console output can look fine while the platform receives nothing due to config/env mismatch.
Common Mistakes to Avoid
These are the failure modes that tend to show up a week later—right when someone asks why cart recovery revenue fell.
- Only initializing after login: you’ll lose anonymous browse/cart events, which are the backbone of abandonment recovery.
- Switching identifiers during the upgrade: moving from email-based identify to ID-based identify without a migration plan creates duplicates and breaks “repeat buyer” segmentation.
- Renaming events “for cleanliness” mid-upgrade: it’s tempting, but it turns into a segmentation rewrite project and introduces gaps during rollout.
- Property type drift: sending
priceas a string in one version and a number in another will quietly break filters, liquid formatting, and analytics. - Not checking device associations: push token mis-association leads to suppressed sends, low delivery, or messages landing on the wrong device.
Summary
Upgrade to Flutter SDK 2.x when you’re ready to protect tracking accuracy—not just update packages. If identity stitching and event parity hold, your cart recovery, repeat purchase, and winback automations stay stable through the release.
Implement 2.x Upgrade with Propel
If you want the upgrade to land without retention regressions, treat it like a measured instrumentation rollout: identity rules first, event parity second, then journey validation. That’s the approach we typically run alongside teams using Customer.io, especially when cart recovery and replenishment flows are sensitive to missing or anonymous events.
If it’s helpful, book a strategy call and we can map your current event contract to the 2.x implementation, plus a QA plan that proves your key segments and triggers still behave before you scale the rollout.