Saaspocalypse
Plan de migration

Migrer hors de Klaviyo — phase par phase.

Les migrations Klaviyo se jouent sur trois spécificités : les API Profiles + Events paginent par curseur avec un burst de 10 req/s, le moteur Flows n'a pas d'« export » public — il faut rebâtir la logique de trigger depuis l'inventaire UI — et vos webhooks Shopify doivent re-pointer en lockstep avec la bascule, sinon vous double-facturez les boîtes mail de vos clients pendant une semaine.

6-10 weeks de bout en boutForfaitParallel run avant basculeLe code est à vous

Les phases, taillées pour Klaviyo

Chaque phase ci-dessous, c'est la version spécifique Klaviyo de notre démarche standard. Même structure à chaque mission, des détails par SaaS.

  1. Audience + Flow audit

    1 week

    We inventory every active Flow, every Segment, every signup Form, and every SMS short code. Most stores have 20+ Flows that compounded over years — about half are no longer firing or are sending to inactive segments.

    Screenshot every active Flow as a single-page reference (the API can't export the trigger logic)
    List every Segment with its filter rules and current size
    Inventory active Forms (popups, embedded) and their UTM rules
    Audit SMS senders (short codes vs long codes, carrier compliance state, opt-in records)
    Map Shopify webhooks currently firing into Klaviyo (orders, refunds, abandoned checkouts, fulfillment)
    Ce que vous repartez avec

    A Flow Inventory + Segment Catalogue + the Shopify webhook switchover plan.

  2. Schema + suppression model

    1 week

    Profiles get a single Postgres table, deduped on email and phone with a unique index. Suppression and unsubscribe state flip booleans instead of inflating a bill. We preserve the Klaviyo `profile_id` for backwards compatibility with anything pointing at it.

    Design `profiles` table with dedupe on (lower(email)) and (E.164 phone)
    Design `events` (or `profile_events`) table for the activity stream
    Design `suppressions` with reason codes (hard bounce, unsubscribe, complaint, manual)
    Plan the SMS sender flow direct to Twilio (no Klaviyo markup) + 10DLC / short-code compliance
    Decide attribution windows up front so reporting agrees with Shopify + GA4 from day one
    Ce que vous repartez avec

    Schema migrations + a documented attribution model + a Twilio sender plan.

  3. Extract via Klaviyo APIs

    1-2 weeks

    Profiles, events, lists, segments and metrics come out via the v2024-XX REST APIs. Throttling matters here — burst at 10 req/sec, sustained ~150 req/min, and segment-level extraction is a separate dance.

    Authenticate via a Private API Key (server-side only)
    Paginate profiles with the `page[cursor]` parameter (the JSON:API style)
    Pull every event with a `filter=greater-than(datetime,…)` window — chunk by date or you'll time out
    Extract list and segment memberships separately (segments aren't materialised; you re-derive them)
    Throttle to stay under the burst + steady-state limits; the cursor lets you resume
    Ce que vous repartez avec

    A re-runnable extract script + a reconciliation report against Klaviyo's own dashboard.

  4. Build + weekly demos

    3-5 weeks

    Three Flows ship in week one (welcome / abandoned cart / post-purchase). Templates become React Email components in your repo. SMS goes direct to Twilio. By end of phase your team is sending the weekly newsletter from the new product.

    Build the Flows engine on Inngest — every step a typed function with retries
    Templates as React Email / MJML, version-controlled, previewed in CI against Litmus
    Email sends via Amazon SES or Resend (fractions of a cent per send, no contact-tier multiplier)
    SMS via Twilio direct — no markup, you handle 10DLC / short-code registration once and own it
    Reporting in Metabase against the same Postgres — drill-downs agree with the chart
    Ce que vous repartez avec

    Three live Flows + weekly campaigns running from the new product on a staging domain.

  5. Parallel run + Shopify cutover

    1-2 weeks

    Shopify continues to fire webhooks into Klaviyo for a fortnight while the new product mirrors them. Daily reconciliation compares opens, clicks, conversions. Then we switch the webhook endpoints on a Tuesday morning.

    Dual-write Shopify webhooks via a Cloudflare worker (Klaviyo + new endpoint)
    Daily reconciliation: sends, opens, clicks, attributed revenue
    Move SMS sender identity (short code or 10DLC long code) — the carrier paperwork is the long pole, start week 1
    Suppress all but one Klaviyo Flow during the final week so we're not double-sending
    Cut Shopify webhook endpoints to the new product, leave Klaviyo on as read-only
    Ce que vous repartez avec

    A reconciliation dashboard showing seven days of zero drift + a signed sign-off from the head of marketing.

  6. Cutover + Klaviyo read-only

    1 day + 90-day fallback

    Klaviyo Flows get paused (not deleted — kept for compliance), Shopify webhooks point cleanly at the new endpoints, the SMS sender identity moves over, auto-renewal cancelled.

    Pause every Klaviyo Flow (don't delete — Klaviyo holds the unsubscribe records you may need)
    Confirm SMS sender identity has fully migrated to Twilio
    Verify Shopify webhook delivery to the new endpoints with synthetic events
    Lock Klaviyo to read-only / viewer role
    Cancel Klaviyo auto-renewal in writing
    Ce que vous repartez avec

    Cutover Runbook + a confirmed SMS sender migration + a quiet inbox where the renewal email used to land.

Les API Klaviyo qu'on tape vraiment

Les endpoints concrets qu'on utilise pour extraire vos données pendant la phase de parallel run. Les scripts d'extraction restent — ils resservent à chaque renouvellement.

Get profiles
GET https://a.klaviyo.com/api/profiles/
Paginate every profile via the `page[cursor]` parameter, with the API revision header pinned
Get events
GET https://a.klaviyo.com/api/events/
Pull the activity stream — chunk by date window or you'll time out
Get metrics
GET https://a.klaviyo.com/api/metrics/
Inventory every event type (Placed Order, Viewed Product, etc.) so the new schema is exhaustive
Get lists
GET https://a.klaviyo.com/api/lists/
Migrate static list memberships (subscribers, VIPs, etc.)
Get segments
GET https://a.klaviyo.com/api/segments/
Read segment filter logic — segments are derived, not stored, so we re-derive them in SQL
Get list profiles
GET https://a.klaviyo.com/api/lists/{list_id}/profiles/
Pull the current membership of each list (needed for the initial backfill)
Get campaigns
GET https://a.klaviyo.com/api/campaigns/
Inventory campaign history for reporting parity
Get flows
GET https://a.klaviyo.com/api/flows/
List Flow metadata (the trigger logic is opaque — rebuild from the screenshots inventory)

Les pièges propres à Klaviyo

Ce qu'on a appris à la dure (ou ce que la doc minimise). On les met sur la table dès le kick-off, comme ça personne n'est surpris en semaine 6.

Ce qui reste en place

Une migration marche quand elle est cadrée honnêtement. Voilà ce qu'on ne touche pas — par choix.

  • ·Klaviyo's CDP product — most stores don't actually use it; we sync direct from Shopify / your warehouse
  • ·Reviews — handled by a dedicated tool (Stamped, Junip, Yotpo) if you need it, not bundled
  • ·Predictive Analytics models — replaced with explicit SQL definitions you can read
  • ·Mobile push and in-app messages — scoped separately if mobile is a real channel
  • ·Klaviyo's native A/B testing UI — replaced with feature flags on the send template
  • ·Klaviyo Forms templates — your popups become first-party React components on your own domain

Cadrer une migration Klaviyo.

Dites-nous votre nombre de licences, la date de fin de contrat et les intégrations que vous ne pouvez pas perdre. On revient sous un jour ouvré avec un cadrage forfaitaire et un calendrier calé sur votre renouvellement.

Cadrer une migration Klaviyo

Un jour ouvré. NDA + DPA sur demande.