Skip to main content

Klaviyo Integration - Complete Guide

Priority: P0 - Blocking multiple marketing initiatives Owner: Chip Stakeholder: Morgane (Marketing)


Why This Matters

Morgane's marketing projects are blocked until we can send user behavior data TO Klaviyo:

Blocked ProjectWhat It Needs
Repurchase campaignsTrigger when test stock is low
User reviews + NPSSurvey after test completion
In-app notificationsKlaviyo SDK for push messages
Revamped onboardingBehavior-based activation emails

"The triggers for Klaviyo from the app will be very essential in order to encourage the one-time purchasers to buy again or to swap to subscription!" — Morgane


The Big Picture

Current State: One-Way (Read Only)

Problem: We can read Klaviyo data, but can't push app behavior back to Klaviyo.

Target State: Two-Way Sync


Complete System Flow

This diagram shows everything - from user action to marketing automation:


What Klaviyo Needs to Know

Profile Properties (14 total)

These are the fields we'll sync to each Klaviyo profile:

Property Details

PropertyTypeWhen UpdatedSource
total_tests_completedintegerEvery testCount readings
last_test_datedatetimeEvery testreading.created
first_test_completedbooleanFirst testDerived
days_to_first_testintegerFirst testShopify order date
days_since_last_testintegerDaily batchCalculated
avg_tests_per_weekfloatDaily batch30-day rolling
test_stock_percentageinteger 0-100Every testLoop or Shopify
tests_remainingintegerEvery testLoop or Shopify
subscription_planstringEvery testLoop data
user_genderstringProfile updateApp onboarding
user_ageintegerProfile updateApp onboarding
purchase_motivationstringProfile updateApp onboarding
hormone_tracking_goalstringProfile updateApp onboarding
app_first_openeddatetimeFirst openFirebase event

Test Stock Calculation

This is the key feature for reorder campaigns:

Trigger Thresholds

Stock %Klaviyo SegmentEmail Flow
75%stock_warning_75Educational nurture
50%stock_warning_50"Halfway through"
25%stock_warning_25Reorder reminder
10%stock_urgentUrgent restock
0%stock_emptySubscription upsell

User Segmentation

By Testing Frequency

SegmentDefinitionKlaviyo Condition
Power users>3 tests/weekavg_tests_per_week > 3
Active1-3 tests/weekavg_tests_per_week >= 1 AND <= 3
Occasional1-3 tests/monthavg_tests_per_week < 1 AND days_since_last_test < 30
Inactive30+ days no testdays_since_last_test >= 30
Never testedPurchased, 0 teststotal_tests_completed = 0

By Purchase Type

SegmentKlaviyo Condition
One-time buyerssubscription_plan = 'one_time'
Light subscriberssubscription_plan = '4_tests'
Medium subscriberssubscription_plan = '8_tests'
Heavy subscriberssubscription_plan = '12_tests'

Opportunity Matrix

QuadrantWhoAction
Top-RightSubscriber + Power UserRetention focus, VIP treatment
Top-LeftSubscriber + InactiveChurn risk, re-engagement
Bottom-RightOne-time + ActiveUpsell to subscription
Bottom-LeftOne-time + Never testedActivation campaign

Marketing Automation Flows

Flow 1: First Test Completed

Flow 2: Test Stock Depletion

Flow 3: Win-Back Campaign


In-App Notifications (Phase 5b)

The Klaviyo SDK is now installed in eli-app (Phase 5, Zeeshan). The SDK foundation (init, profile, push token) is in place. What remains is enabling in-app message rendering and Klaviyo push handling.

Current state: SDK installed and initialized, profile identification works, push token forwarded. In-app message display and Klaviyo push routing still need to be wired up (Phase 5b).


Email Resolution

~6% of users have different emails in the app vs Shopify. We prioritize Shopify email:

Coverage: 94% of purchasers have linked Shopify accounts.


Data Volumes

From existing BigQuery data:

MetricCount
Klaviyo profiles36,832
Users with completed tests1,636
Shopify-linked users94%
Abandoned checkouts870

Backfill Strategy

  1. One-time backfill: Query BigQuery for all historical test data
  2. Real-time going forward: Hook into test completion flow

The existing user-journey-records.sql query already links:

  • Klaviyo profiles → Firebase accounts → Biometrics test data

Confirmed with Morgane

ItemStatusNotes
Cart abandonmentAlready handledKlaviyo-Shopify native integration
Test kit identificationUse existing querySame as diurnal curve completion
App download trackingUse first_openCan't track actual downloads
Backfill historical dataApprovedRun once, then real-time

Implementation Phases

Phase 5: Mobile SDK --- DONE (EXM-996, Zeeshan, 2026-01-27)

Implemented in eli-app on the development branch. PR #586.

What was built:

ComponentFileWhat It Does
Klaviyo servicesrc/services/klaviyo.tsSDK init, setProfile, createEvent, resetProfile, setPushToken
Environment configsrc/config/environment.ts, .env-cmdrc.js, src/types/env.d.tsREACT_APP_KLAVIYO_API_KEY wired through env
Profile identificationsrc/services/auth.tssetProfile() on all auth flows (email, Google, Apple) + resetProfile() on sign out
Push tokensrc/services/messaging.tsFCM token forwarded to Klaviyo via setPushToken()
Measurement eventsrc/screens/.../MeasurementCalculating.tsxmeasurement_completed event with readingId, hormoneType, userId
Notification eventsrc/services/app.tsreminder_notification_opened event when user opens a protocol reminder
Notification datasrc/services/notification.ts, protocolNotifications.tsLocal notifications now carry userId, hormoneType, type in data payload

Profile data synced to Klaviyo on login:

  • email, externalId (user.id), firstName, lastName, location.timezone

Events tracked:

  • measurement_completed --- readingId, hormoneType, userId
  • reminder_notification_opened --- userId, hormoneType

Remaining mobile work (Phase 5b):

  • In-app messages (banners, modals) --- not yet enabled
  • Klaviyo push notification handling (handlePush) --- not yet wired
  • app_first_opened event --- not yet tracked

Phase 1: Core Test Events (P0) --- NOT STARTED

  • Backend: Create eli-backend-api/src/modules/klaviyo/ module
  • Hook into readings.controller.tshandleAnalysis() after test completion
  • Sync profile properties: total_tests_completed, last_test_date, first_test_completed, days_to_first_test
  • Email resolution via Shopify service (94% Shopify email, 6% app email fallback)

Phase 2: Test Stock (P1) --- NOT STARTED

  • Calculate from Loop subscriptions or Shopify orders
  • Sync: test_stock_percentage, tests_remaining, subscription_plan

Phase 3: User Demographics (P2) --- NOT STARTED

  • Sync on profile updates via users.controller
  • Properties: user_gender, user_age, purchase_motivation, hormone_tracking_goal

Phase 4: Batch Metrics (P3) --- NOT STARTED

  • Daily Cloud Scheduler job in eli-kpi
  • Properties: days_since_last_test, avg_tests_per_week

Success Metrics

MetricCurrentTarget
Reorder trigger latencyManual< 1 minute
Profile sync success rateN/A> 99%
Email resolution accuracyN/A94%+
Test stock visibility0%100% of users


Document History

DateAuthorChanges
2026-01-27ChipUpdated with Phase 5 implementation status (EXM-996, Zeeshan). Marked remaining phases.
2025-01-26ChipConsolidated all marketing dashboard docs into single source