Pricing

Moving your list off Mailchimp without losing your history

What Mailchimp's export actually contains, what it leaves out, and why the suppression list has to move first: a destination-neutral migration guide.

By Dana Okafor ·

Mailchimp will hand you every contact, split by status, plus tags, notes, custom fields, and the timestamp and IP address of when each person opted in. It will not hand you your automations, and your templates come out as static HTML rather than anything the destination can reuse directly. None of that is the part that goes wrong.

The part that goes wrong is the unsubscribes, the cleaned addresses and the complaints. Drop them on the way over and you mail people who told Mailchimp, explicitly, to stop. That is a legal problem under CAN-SPAM and GDPR alike, and it is also the fastest way to burn the reputation of whatever domain you send the next campaign from.

If cost is what’s driving the move, the full price comparison across ten tools is worth checking before you settle on a destination; this post assumes you already have one.

Key Takeaways

  • Mailchimp’s export splits contacts into four files by status: subscribed, unsubscribed, cleaned and non-subscribed. Get all four, not just the active one.
  • The unsubscribed and cleaned files are the suppression list. They have to arrive at the destination as a block on sending, not as ordinary contacts.
  • Mailchimp exports the signup timestamp and IP address behind each opt-in (OPTIN_TIME, OPTIN_IP). Most destinations have nowhere native to put them, so decide where that record lives before you import.
  • Automations don’t export. Templates export as raw HTML, without whatever merge-tag or block system built them.

What actually comes out of Mailchimp

Exporting an audience produces a ZIP file with a separate CSV for each subscription status, rather than one file with a status column:

FileWho’s in it
SubscribedContacts who can currently receive your campaigns
UnsubscribedContacts who opted out, including most spam complaints (see below)
CleanedAddresses that hard bounced, or soft bounced repeatedly, and are no longer deliverable
Non-subscribedContacts who entered the audience without opting in to marketing, most often through a transactional send

Each row carries the standard audience fields, plus tags, contact notes, a MEMBER_RATING activity score, LAST_CHANGED, and two internal ID columns (LEID, EUID) that only mean anything inside Mailchimp. Report data, meaning opens and clicks on individual campaigns, is not in the file: that lives in the campaign reports, not the audience export.

Spam complaints deserve a note of their own. A contact who reports one of your campaigns as spam is moved into Mailchimp’s abuse complaints area and automatically unsubscribed, so they land in the unsubscribed file along with everyone who clicked an unsubscribe link. If you only pull a segment of “recently unsubscribed” rather than the full unsubscribed file, you can miss ones that go back further. Take the whole file. Mailchimp keeps billing you for most of that file until you archive it by hand, a separate problem from moving it; see paying for contacts you never email for how much that’s actually costing you before you leave.

The suppression list is the part that actually has to move

Everyone budgets time for moving the subscribed contacts. Fewer people budget time for the other three files, and that is backwards: a bad import of the subscribed file is recoverable, you just don’t send until you fix it. The unsubscribed and cleaned files are the only record that certain people must never be emailed again, and there’s no reconstructing it once it’s gone.

Concretely: import the unsubscribed and cleaned files, but import them as suppressions or as contacts with an opted-out status, not as ordinary active contacts. A CSV that only has an email address column with no status information gives the destination no way to tell an opted-out address from a new one, so it gets treated as new. That is how a cleaned address gets mailed again three weeks after the migration, from a domain that has no bounce history yet to protect it.

Mailchimp’s own cleaned-contact page is explicit that a cleaned address can’t be reactivated, “even though you can view or export them.” That line describes the export, not a workaround: Mailchimp is telling you cleaned means cleaned, and whatever accepts that file downstream should treat it the same way.

EmailFig’s own importer works from a status column for exactly this reason: an unsubscribed row lands as unsubscribed with a suppression behind it, and a cleaned row lands as cleaned and off the list, so a later re-import can’t quietly resurrect either one. That’s covered in importing contacts from a CSV and in more depth in how the suppression list works. Whatever destination you’re moving to, look for the same guarantee before you trust it with the file.

Mapping the statuses, not just the addresses

Mailchimp’s contact statuses are subscribed, unsubscribed, cleaned, pending and non-subscribed (Mailchimp’s own name for contacts added without an opt-in, most often through a transactional send). Most destinations use a similar shape but not identical names or identical rules, and the mapping is where migrations quietly go wrong, because a status name that looks equivalent can carry different downstream behavior.

The mistake to watch for is collapsing “cleaned” into “unsubscribed.” They are not the same thing. An unsubscribed contact chose to leave and, on most platforms including Mailchimp’s own, can opt back in. A cleaned contact has a broken address, and re-subscribing it doesn’t fix the address, it just queues up another bounce. If your destination has a distinct “invalid” or “cleaned” status, use it. If it only has active and unsubscribed, put cleaned addresses on the suppression list rather than marking them unsubscribed, so nothing ever tries them again.

Pending contacts, meaning people who started a double opt-in signup but never clicked the confirmation link, are the other edge case. They never consented, so they should not become active contacts on the other side. Most destinations that support double opt-in have a pending status you can drop these into so the confirmation step gets asked again rather than skipped; EmailFig’s version of that is covered in setting up double opt-in on a list.

Mailchimp’s export includes four fields most migrations never look at: OPTIN_TIME and OPTIN_IP, the moment and address behind the original signup, and CONFIRM_TIME and CONFIRM_IP, the moment and address behind a double opt-in confirmation click. That is your proof of consent, and under GDPR you’re expected to be able to produce it.

Few destinations have a native import field for someone else’s historical opt-in timestamp, since the platform’s own signup flow generates that timestamp itself. The honest options are to archive the original Mailchimp export (do this regardless) or write the date and IP into a custom field so they stay attached to the contact as reference data, rather than feeding the destination’s own consent trail. What you should not do is let the import date stand in for the opt-in date: it overstates how recently someone actually agreed to hear from you.

Tags, groups and segments

Mailchimp gives you two ways to categorize a contact, and they mean different things. Tags are free-form labels, visible across every audience in the account. Groups, organized under interest categories, are audience-specific and usually collected at signup, closer to a set of topic subscriptions than a label. Both export as columns on the contact row.

Most destinations only have one concept, usually called tags, so both collapse into it on the way over. Fine for tags, but a group is really a topic someone opted into, which behaves like a subscription with its own opt-out, not a label you applied yourself. If the destination keeps those separate the way EmailFig separates tags from lists, a group export is a better fit for the list side than the tag side.

Segments are the one thing that doesn’t export as data at all. A Mailchimp segment is a saved rule, not a stored list of members, so there’s nothing in the contact CSV that reconstructs it. You rebuild the rule by hand once you’re on the destination, using tags and groups as the inputs.

Custom fields and merge tags

Mailchimp calls per-contact data fields merge fields, and they export as ordinary columns alongside the built-in ones, which most destinations can map directly. What doesn’t carry over is the merge tag syntax used inside a template body, *|FNAME|* in Mailchimp’s case: your new tool almost certainly uses a different token, so every template that personalizes a subject line or a greeting needs those tags rewritten by hand. There’s no export step that fixes this, because it lives in the template file, not the contact data.

What doesn’t come with you: automations and templates

Mailchimp’s account data export covers campaigns, audiences, reports and templates, and automations aren’t on that list. There is no file that reconstructs a welcome series or a re-engagement flow: you rebuild the logic from scratch on the destination, which is real work if you have anything beyond a single welcome email.

Templates fare a little better in that they do export, as a folder of HTML files. What you get is markup, not a rebuildable design: no editable blocks, no saved layout, no merge-tag wiring, and the CSS is usually inlined for email clients rather than written for a second round of editing. Treat the HTML as a visual reference for rebuilding the template in the new tool, not as something you drop in and expect to work.

Sequencing the cutover so you don’t burn a new domain

A clean list means nothing if the domain sending it has no history. Authenticate the sending domain first, with SPF, DKIM and ideally DMARC, before any of the imported contacts see a message from it. Warm it: start with a small, engaged slice of the list and grow the volume over days rather than emailing everyone in the first send. A domain with no sending history that suddenly mails 30,000 people looks like the start of a spam run to every major inbox provider, regardless of how clean the list actually is.

Run both platforms in parallel for a short overlap rather than cutting over in one move: keep Mailchimp sending on its own schedule while the new domain warms, then shift volume across once it has a few clean sends behind it. If the destination sends through your own Amazon SES account, what SES actually costs once you add the parts that aren’t the headline per-email rate is worth knowing before the warming period, not after.

The one thing not to do is point the entire migrated list, suppressions included, at a cold domain on day one. It’s the single most common way a migration turns a clean list into a deliverability problem instead of avoiding one.

Checklist

  • Export all four Mailchimp status files: subscribed, unsubscribed, cleaned, non-subscribed.
  • Import unsubscribed and cleaned as suppressions or opted-out contacts, never as active ones.
  • Map pending contacts to a pending or unconfirmed status, not to subscribed.
  • Decide where OPTIN_TIME and OPTIN_IP live on the destination before you import, even if that’s just an archived copy of the original file.
  • Split Mailchimp groups from Mailchimp tags if the destination distinguishes a subscription from a label.
  • Rebuild merge tags and automations by hand; neither survives the export.
  • Authenticate and warm the sending domain before the first campaign goes out from it.

None of the above is specific to where you’re going. If where you’re going happens to be EmailFig, importing a CSV works from the same status-column logic described above, and the Mailchimp comparison covers the rest of what’s different once the list has actually arrived.

Keep reading

All posts →