Skip to main content

Migrating from Klaviyo

A practical, consent-safe path from Klaviyo to Hober: export, transform, import, run both in parallel, then cut over. Written for a marketer with a spreadsheet, not a data engineer.

The one rule that governs everything below: consent state must survive the move exactly. A suppressed profile that arrives as an active subscriber is how migrations destroy sender reputations. Hober's import is built to make the safe path the easy one — opted-out state stored in Hober always survives re-imports.

1. Export from Klaviyo

  • Profiles: Lists & Segments → select a list → Manage list → Export list to CSV. Export each list you intend to keep, plus your master list.
  • Suppressed profiles: Profiles → Suppressed → export separately. You will not import these as subscribers — see step 3.
  • Templates: open each email template → export/copy the HTML. There is no bulk template export on most plans; budget manual time per template.

2. Transform the profile CSV

Hober's importer maps columns by header name. Build this header set:

Hober columnFrom KlaviyoNotes
emailEmailRequired — rows without it fail, the rest continue.
external_idyour CRM/user ID propertyOptional but strongly recommended: it's what unifies imported profiles with SDK and server events later.
attributesany properties you keepA JSON object per row, e.g. {"first_name":"Ana","plan":"pro"}. Invalid JSON is ignored field-by-field, the row still imports.
consent_typeconsent statusexpress for profiles with explicit opt-in (Klaviyo "subscribed"), implied otherwise. See the semantics below — they are not interchangeable.
consent_sourcee.g. klaviyo_migrationFree-text provenance; name the migration so the ledger reads honestly later.
consent_timestampconsent date if exportedRFC 3339 or YYYY-MM-DD.

Consent semantics that protect you:

  • express overwrites prior consent state — assert it only for profiles with a real, attributable opt-in.
  • implied only seeds consent where none exists — a stored opt-out in Hober always survives an implied re-import. When in doubt, use implied.
  • Rows with consent metadata but no consent_type (or an unknown type) fail validation individually; the import continues.

3. Suppressed profiles: do not import them

Leave Klaviyo's suppressed export out of the subscriber import entirely. Keep the file: it is your audit record. If a suppressed person genuinely re-subscribes later, they come back through a real opt-in path (signup form, preference center) — never through a CSV.

Hober enforces consent and suppression at send time on every channel, so the guardrail catches mistakes — but the clean migration is to never create the subscriber row at all.

4. Import

Dashboard → Subscribers → Lists → Import from CSV (max 50 MB per file; split larger exports). The import runs asynchronously with per-row error reporting: failed rows are named with reasons, successful rows proceed. Import list-by-list to preserve your list structure.

5. Templates

Klaviyo templates are HTML with Django-style variables; Hober email content uses Liquid merge tags. The HTML body ports directly; variables need translation (e.g. {{ first_name|default:"there" }} → Liquid's {{ first_name | default: "there" }} — similar, not identical). Paste the ported content into a Hober template, then use preview and a test send to yourself before anything ships. Validation catches undefined merge tags before send, not after.

6. Parallel run

Do not flip traffic on day one:

  1. Week 1–2 — Hober sends to a slice. Route one campaign type (or one engaged segment) through Hober while Klaviyo carries the rest. Follow the domain warm-up guidance if Hober sends from a new subdomain.
  2. Suppression sync, both directions, manually. Until cutover, export Klaviyo's new unsubscribes weekly and remove them from the affected Hober lists; check Hober's suppression ledger (Deliverability page) before any Klaviyo send to the same audience. This is the tedious part — keep the window short.
  3. Compare deliverability. Hober's per-channel deliverability dashboard shows delivery/bounce/complaint rates; hold the ramp if bounces exceed 2% or complaints 0.1%.

7. Cutover checklist

  • All lists imported; spot-check counts against Klaviyo per list.
  • Suppressed export retained (not imported); archived with the migration date.
  • Templates ported, previewed, test-sent.
  • Journeys/flows rebuilt in Hober and activated with entry conditions verified.
  • Domain authentication (SPF/DKIM) green in the channel's deliverability panel.
  • Final Klaviyo unsubscribe export applied.
  • Klaviyo flows paused before Hober journeys activate on the same triggers (double-send window: zero).
  • Klaviyo account left read-only for one billing cycle as the rollback path.

Prefer the built-in preset

The manual transform in step 2 now has a shortcut: in the import dialog, choose File format → Klaviyo export and upload Klaviyo's CSV as-is. The importer applies this guide's mapping automatically — Email becomes the subscriber email, the consent status column translates consent-safely (subscribed → express with klaviyo_import provenance; unsubscribed and suppressed rows are skipped, never imported; everything else → implied), and the remaining columns become snake_cased attributes. Skipped rows appear in the failed count with their reason, so the numbers stay honest.

Steps 2–3 remain the reference for what the preset does — and the manual path still works when you need custom control.

Migrating from Braze instead?

That path has its own guide and import preset — and Braze templates are already Liquid, so the template step is renames, not syntax translation.