Skip to content

Klaviyo → AcelleMail Migration — Visual Walkthrough

Export your Klaviyo profiles as CSV, import into AcelleMail via the 6-click wizard. Visual walkthrough plus power-user API path for large Klaviyo accounts.

Before you start

You'll need:

  • A Klaviyo account with profile-export permission (Owner or Admin role)
  • An AcelleMail installation up and running
  • ~45 minutes for <100k profiles + tags + custom properties

Klaviyo's profile model is rich (event history, conditional segments, predictive metrics). The CSV migration preserves identity + custom properties; behavioural segments + flows are rebuilt manually in AcelleMail's visual builder.

Export from Klaviyo

In Klaviyo's left sidebar, click AudienceLists & Segments → choose the list to export. On the list page, Manage ListExport List to CSV.

Klaviyo asks which properties to include — select All (or trim down if you have hundreds of custom properties you don't need). The file prepares in the background; Downloads sidebar item shows the download link when ready (usually <5 minutes for <100k).

Exported CSV includes: email, all standard + custom profile properties, opt-in date, source, last activity timestamp.

For segment-based migration (e.g. only profiles matching "Engaged in last 30 days"), use Segments → [segment name] → Export Segment — same flow, scoped output.

Import into AcelleMail (the same 6 clicks for every source)

Once you have the CSV exported from your previous platform, the import flow in AcelleMail is identical regardless of where the data came from.

1. Open your destination list

In AcelleMail's sidebar, click Audience → choose the list that will receive the migrated subscribers (or create a new one — New list button top-right).

Lists index

You'll see a per-list overview card with subscriber counts:

List overview

2. Click "Import" in the list toolbar

The wizard entrypoint is on the list detail page:

Import entry point

3. Upload your CSV

Drop the CSV file from the previous platform into the upload area:

Upload empty state

AcelleMail parses the file and confirms detection:

Upload success

4. Map the columns

The wizard auto-detects standard columns (email, first_name, last_name) and shows green Mapped to EMAIL chips. Adjust manually for any non-standard column from the source:

Map columns

5. Pick duplicate handling

In the same screen, choose what AcelleMail does when a subscriber already exists in this list:

  • Skip — keep the existing row, don't overwrite
  • Update — overwrite name/tags/custom fields with values from the CSV
  • Unsubscribe — mark existing rows as unsubscribed (rare; used when re-importing an opted-out list)

6. Run the import

Click Start import. The job runs in the background — close the popup, work elsewhere, return to Audience → [list] → Import to see progress:

Import history

You'll see PendingRunningComplete per import job, with rows-imported / rows-skipped / errors counts.

After the import

  • Verify list count matches your expected size (rows that failed validation appear in the Errors column with a downloadable error CSV).
  • Re-tag if needed — for behavioural data that doesn't fit a CSV column (e.g. "opened campaign X"), you may need to re-create the tag via segmentation rules.
  • Pause for warm-up — if the imported list is large (>10k) and your sending IP is new or recently rotated, run a short warm-up campaign to your most-engaged 10% before the full send. See IP warm-up best practices for the schedule.

Rebuilding Klaviyo flows in AcelleMail

Klaviyo's flows map to AcelleMail's Automations. Equivalent triggers:

Klaviyo trigger AcelleMail trigger
Subscribed to list Subscribed to list
Added to segment Tag added (via segment-to-tag mapping)
Metric event (Shopify, custom) Custom event (API)
Profile property change Field value change
Date property matches Date relative
Clicked email link Link clicked

For Klaviyo's predictive analytics + AI features (predicted CLV, churn risk), AcelleMail doesn't have direct equivalents — these are Klaviyo-specific advantages. If you depend on them, evaluate whether the cost savings of self-hosting justify rebuilding those signals via your own data pipeline.

Merge-tag syntax differences

Klaviyo AcelleMail
{{ first_name }} (root scope) {{ subscriber.first_name }}
{{ last_name }} {{ subscriber.last_name }}
{{ email }} {{ subscriber.email }}
{{ organization.web_view_url }} {{ web_view_url }}
{{ organization.unsubscribe_url }} {{ unsubscribe_url }}

Klaviyo's Jinja-style conditionals ({% if profile.tags contains 'vip' %}) work in AcelleMail's email builder with minor adjustments (use subscriber.tags instead of profile.tags).

Advanced: API-driven migration with Klaviyo's profile export endpoint

For >250k profiles or for ongoing sync from a CRM-of-record, Klaviyo's API supports bulk export.

Export from Klaviyo via API:

# Klaviyo Private API key from Settings → API Keys
curl -X GET "https://a.klaviyo.com/api/profiles/?page[size]=100&page[cursor]=" \
  -H "Authorization: Klaviyo-API-Key <KLAVIYO_PRIVATE_KEY>" \
  -H "revision: 2024-10-15" \
  -o klaviyo-profiles.json

Klaviyo paginates via cursor; loop until links.next is null.

Import into AcelleMail via REST API:

ACELLE_TOKEN="..."
ACELLE_LIST_UID="..."

jq -c '.data[] | {email: .attributes.email, first_name: .attributes.first_name, last_name: .attributes.last_name}' klaviyo-profiles.json \
  | while read sub; do
      curl -X POST "https://acellemail.com/api/v1/subscribers" \
        -H "Authorization: Bearer $ACELLE_TOKEN" \
        -d "{\"list_uid\":\"$ACELLE_LIST_UID\",\"subscriber\":$sub}"
    done

For Klaviyo-specific behavioural data (events table, metric aggregates), you'll need to bridge via your own ETL — AcelleMail doesn't have direct event-stream ingestion. The path most teams take: keep the rich behavioural store in your data warehouse (Postgres / BigQuery / Snowflake), use AcelleMail's API to push tag/segment updates based on warehouse-computed signals.

Related articles

19 comments

13 comments

  1. akira.tnk88
    Question on DNS migration step — when you say 'add new include alongside old', does that work with strict DMARC alignment or does mixing two SPF includes break the alignment check?
    1. admin
      We tested this with up to 1M subscribers on a $40/mo VPS. Past that you start needing query optimization. Below that, the defaults are fine...
  2. bos.devops
    Tip for anyone planning this: do a dry-run of the import with a small test list first. We caught a CSV encoding issue (Excel saved BOM-prefixed UTF-8) that would've affected all 60k rows.
    1. admin
      yep, same pattern works for us. Thanks for sharing.
  3. sofia.costa.pt
    Completed this migration in Q1. The list-cleanup step is even more important than this guide makes it. We had 40k subscribers, exported, found that 6k were already on Mailchimp's suppression list. Importing those would've torched our new sender reputation.
  4. m.schmidt78
    What about subscribers who unsubscribed via Mailchimp's preference center? Does the suppression-list import capture those, or just outright unsubscribes? fwiw
    1. admin
      we don't recommend that approach in production. it works in dev but has subtle race conditions under concurrent load. stick with the documented pattern...
  5. d.cohen.tlv
    Id push back on the 'random recipient split' for the parallel period. If your campaigns are time-sensitive (flash sales etc), random splitting causes weird timing fragmentation. We split by audience segment instead — simpler ops
  6. cmendoza.mx
    year 1 cost ended up matching this guide's estimate almost exactly. year 2 was even better because the vps upgrade we needed was a one-time $20/mo bump.
  7. rafa.silva.br
    Reading this 2 weeks into our Mailchimp migration. The 8-week timeline is conservative but accurate — we tried to compress to 4 weeks and got bitten by exactly the DNS warmup mistake you describe...
  8. aisha.khan.pak
    Bookmarked. We're evaluating a move next quarter and this is the most operationally-realistic guide I've found...
    1. admin
      Thanks. Pass it along if it helps your team.
  9. lucas.bernard.…
    how do you handle the mailchimp-style merge tags in old templates? we have ~50 templates with *|fname|* and don't want to manually rewrite each.
    1. admin
      Yes, that pattern is supported. The undocumented bit is the order — config:cache MUST come after the migration, not before. Updating the docs to make that explicit.
  10. lequan.saigon
    The cost-comparison table is the only honest one I've seen. Most 'AcelleMail vs X' content underestimates the ops cost of self-hosting.
  11. danrey.dev
    Did this last year. Confirming: the cron + worker setup is 80% of the install pain. Once those are running, the rest is documentation-following
  12. aditi.s.bom
    We migrated 90k subscribers last March. The parallel period suggestion (10-25-50-75) saved us — the AcelleMail side hit a deliverability dip on day 3 we wouldnt have caught at 100% cutover. :)
    1. admin
      great real-world detail. Your point about stale running_pid > 30 min as an alert is something we should add to the diagnostic flow.
  13. v.petrova.ru
    For the IP warmup — is dedicated IP worth it at 25k subscribers? Or stick with shared SES?

More in Migration & Comparison