Mailchimp → Ghost
Move a Mailchimp audience into Ghost members with the built-in migrator or a member CSV. Campaign content does not come across, and people who are already Ghost members keep their old newsletter preferences.
Should you make this move?
Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.
Mailchimp
- A broad small-business marketing suite combines email, contacts, forms, and campaigns
- Audience, campaigns, automations, and reporting live in one publishing system
- Pricing, interface complexity, and audience-based billing can become frustrating
- Automation logic, analytics history, and deliverability settings are not very portable
Ghost
- A focused publishing and membership platform is fast and pleasant for writers
- Editors get a purpose-built publishing workflow instead of raw files
- Its narrower ecosystem is less suitable for complex sites and custom application behavior
- Themes, extensions, and content models add maintenance and portability constraints
Ghost: A focused publishing and membership platform is fast and pleasant for writers. This removes a major source-side concern: Pricing, interface complexity, and audience-based billing can become frustrating.
What you lose: A broad small-business marketing suite combines email, contacts, forms, and campaigns. What you inherit: Its narrower ecosystem is less suitable for complex sites and custom application behavior.
Jump to a section
Know the shape of the move.
This timeline assumes
- You are a Mailchimp Owner or Admin, because only those roles can export an audience. You can also sign in to Ghost Admin.
- The move is subscribers into members. Ghost says Mailchimp content cannot be migrated with the built-in tool.
- You will open Mailchimp's ZIP and import the subscribed file. You will not import unsubscribed or cleaned addresses as subscribers.
- The site already documents Mailchimp → Kit and Mailchimp → Substack if the destination is another newsletter, and Ghost → Substack if you later leave Ghost.
What survives the move.
“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.
| Item | Outcome | Impact | What happens | Mitigation |
|---|---|---|---|---|
| Campaigns and automations | lost | critical | Ghost's Mailchimp guide says it is not currently possible to migrate Mailchimp content. The migrator imports members. Ghost(Pro) customers can ask Ghost's migrations team for content help. Self-hosted sites are pointed at Ghost's open-source migration tools. | Export the campaigns you still need as your own archive. Rebuild posts and newsletters in Ghost. |
| Opens, clicks, and purchase history | lost | high | Mailchimp says contact exports do not include email report data such as opens and clicks. The same page lists purchase history, predicted demographics, favorite email client, and social profile data as excluded. A GDPR request for one person is a different export, from that contact's profile. | Download the email reports you still need before you close Mailchimp. Do not expect them inside the member CSV. |
| Unsubscribed and cleaned contacts | manual | critical | An audience export can include subscribed, non-subscribed, unsubscribed, and cleaned contacts. Mailchimp often returns a ZIP of separate CSVs, one per contact type, and keeps that export for 30 days. Ghost's migrator asks you to export the audience and upload the download. | Unzip the file. Upload the subscribed CSV. Keep the other files as a suppression archive, not as a subscriber import. |
| People already in Ghost | partial | critical | Ghost's member import says a new member with subscribed_to_emails true joins every newsletter that has Subscribe new members on signup turned on. An existing member with that value true keeps their current preferences, unless they were unsubscribed from all newsletters. False unsubscribes the member from all newsletters. | Count members who already exist before you import. Plan a second step for the newsletter you want them on. |
| Labels and notes | partial | medium | Mailchimp's export includes TAGS and NOTES, plus audience fields other than language. Ghost's CSV accepts labels in quotes, comma-separated, and a note column. The Mailchimp migrator confirms a subscriber count. It does not document a tag mapper. | If tags matter, use Members, Import members, and map Mailchimp tags into the labels column. |
| Paid Stripe customers | manual | high | Ghost can import stripe_customer_id, or the value auto, which looks up a customer with the same email on the connected Stripe account. complimentary_plan marks a free subscription. Mailchimp's contact export is not a Stripe export. | Add Stripe ids only when you have them from Stripe. Leave the column off for a free list. |
| Opt-in timestamps | partial | medium | Mailchimp includes OPTIN_TIME, CONFIRM_TIME, CONFIRM_IP, and related geolocation fields when it has them. Ghost's created_at column wants ISO 8601, such as 2019-10-30T14:52:08.000Z. Email is the only required Ghost column. | Convert CONFIRM_TIME when you build a CSV. Drop the import if the dates do not parse. |
| SMS contacts | lost | medium | Mailchimp puts SMS contacts in a separate folder in the export, with acquisition time, revocation time, and SMS subscription status. Ghost's member CSV is an email import. Email is required. | Keep the SMS folder in the archive. Do not paste phone-only rows into the member file. |
| Multiple audiences | manual | high | Mailchimp exports one audience, segment, tag, or group at a time. Owners and Admins export audiences. Ghost imports into the publication you are signed in to. | Repeat the export per audience. Label each file with the audience name before you import. |
| Signup source and language | lost | low | Mailchimp says the audience export excludes email signup source and the language field. Ghost's documented columns do not include a language field. | Record language somewhere else if a send depends on it. |
Where each thing goes.
| Source | Destination | Method | Notes |
|---|---|---|---|
| Subscribed CSV | Ghost members | automatic | Ghost Admin, Settings, Advanced, Import/Export, then the Mailchimp migrator. Or Members, Import members. |
| automatic | Required on the CSV path. The migrator reviews the subscriber count before you confirm. | ||
| First and last name | name | transform | Ghost wants one name column if you use the CSV. |
| TAGS | labels | transform | Quote the list and separate labels with commas, as in Ghost's template. |
| NOTES | note | transform | Use the CSV path when notes must move. |
| Subscribed status | subscribed_to_emails | manual | True opts a new member into newsletters that subscribe new members on signup. False unsubscribes them from all. |
| CONFIRM_TIME | created_at | transform | ISO 8601 only. |
| Stripe customer | stripe_customer_id or auto | manual | auto searches the connected Stripe account by email. |
| Unsubscribed and cleaned CSVs | No destination | unsupported | Keep them out of the subscriber import. |
Make the move recoverable.
Create the source-of-truth backup
Keep Mailchimp's ZIP until Ghost's member count matches the subscribed file.
- Export the audience as an Owner or Admin.
- Download the ZIP from Export history before the 30 days end.
- Save the subscribed, unsubscribed, non-subscribed, and cleaned CSVs separately.
- Export any campaign reports you still need, because the contact file does not contain them.
Proof to capture: The ZIP, the four contact files, and the Ghost review count are in the migration folder.
Subscribed file only
Give Ghost the people you may email, and leave suppressions out.
- In Mailchimp, open the audience and export it.
- Unzip the download. Find the subscribed CSV.
- In Ghost, open Settings, Advanced, Import/Export. Sign in to Mailchimp when the migrator asks.
- Upload that file. Read the subscriber count. Import only if the count matches the subscribed file.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
Member CSV for labels and existing members
Set labels, notes, and email subscription on purpose when the migrator is too coarse.
- Build a CSV with email and the optional columns Ghost lists.
- Set subscribed_to_emails true only for people who should receive newsletters.
- Turn Subscribe new members on signup on for each newsletter a new member should join.
- Import from Members. Then list members who already existed and were not added to the new newsletter.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
The things most likely to hurt.
These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.
The whole ZIP is uploaded
The file contains unsubscribed or cleaned addresses.
- Consequence
- Ghost can treat those rows as members you might email.
- Mitigation
- Import the subscribed CSV only. Compare the review count with that file.
Stop if: You cannot tell which CSV is the subscribed file.
Existing members miss the new newsletter
Subscribe new members on signup is on, and some addresses are already members.
- Consequence
- Those people stay on their old newsletter settings. The new send is smaller than the Mailchimp list.
- Mitigation
- Diff the Mailchimp file against current Ghost members before the first send.
Stop if: The first issue must reach every existing member and you have no second step for them.
False unsubscribes everyone
subscribed_to_emails is false on a row for someone who should still get mail.
- Consequence
- Ghost unsubscribes that member from all newsletters, including ones they already had.
- Mitigation
- Use false only for people who must be off every newsletter.
Stop if: You are reimporting the full audience with false as the default.
Do the work in this order.
- Days 1 to 2 · inventory
Count the audience
2 to 4 hours active1 to 2 days elapsedMailchimp's export email waiting- Export the audience.
- Count each CSV in the ZIP.
- List Ghost newsletters and who already exists.
Depends on: Owner or Admin on Mailchimp
Stop / go checkpointWhich file is the import?
Go when: The subscribed count is written down and the other files are archived.
Stop when: The ZIP has not arrived or the files are mixed.
- Day 2 · backup
Archive reports
1 to 3 hours active1 day elapsedReport downloads waiting- Download campaign reports you still need.
- Store the ZIP where it will last past 30 days.
Depends on: Audience export
Stop / go checkpointIs the archive complete?
Go when: Subscribed, suppressed, and report files are saved outside Mailchimp.
Stop when: A report you need is still only inside Mailchimp.
- Days 3 to 5 · pilot
Import and read the count
2 to 4 hours active1 to 2 days elapsedGhost's import waiting- Upload the subscribed file.
- Compare Ghost's review count with the CSV.
- Spot-check labels if you used the CSV path.
Depends on: Archived ZIP
Stop / go checkpointImport for real?
Go when: The review count matches the subscribed file.
Stop when: The count includes another contact type.
- Days 5 to 7 · cutover
Fix existing members, then send
2 to 4 hours active1 to 2 days elapsedA test send waiting- List members who already existed.
- Subscribe them to the new newsletter on purpose.
- Send a test to a small segment.
Depends on: Finished import
Stop / go checkpointSend the newsletter?
Go when: The recipient count matches the people who should get it.
Stop when: Existing members are missing and the issue cannot wait.
- Days 7 to 14 · observe
Watch one real issue
1 to 3 hours active2 to 7 days elapsedOne publish waiting- Compare complaints with the suppression archive.
- Keep Mailchimp read-only until that issue looks right.
Depends on: Test send
Stop / go checkpointClose Mailchimp sending?
Go when: One issue went to the expected members and not to the cleaned file.
Stop when: Unsubscribed addresses received it.
Cut over with a way back.
Cutover
Send the next issue from Ghost to the subscribed list, including members who were already on the site.
- Confirm the imported count against the subscribed CSV.
- Update newsletter membership for people who were already Ghost members.
- Send a test issue to a segment you can check by hand.
- Stop new campaigns in Mailchimp.
- Send the real issue from Ghost and read the recipient count before it goes out.
Proof to capture: The recipient count matches the subscribed file after the existing-member fix, and a cleaned address is absent.
Rollback
Keep sending from Mailchimp if Ghost's member list is short or includes suppressions.
- Do not delete the Mailchimp audience.
- Stop the Ghost send if the recipient count is wrong.
- Export the Ghost member list and diff it against the subscribed CSV.
- Send the issue from Mailchimp if Ghost is missing people who should get it.
Proof to capture: Mailchimp still has the audience, and no Ghost issue went to the cleaned file.
- The review count is higher than the subscribed file
- Existing members are missing from the new newsletter
- A cleaned address appears in Ghost as subscribed
- subscribed_to_emails false was applied to current readers
- The first issue's recipient count is short
Prove the migration worked.
Every blocking check must pass. Capture the evidence before cleanup begins.
| Pass | ID | Check | Method | Expected result | Evidence |
|---|---|---|---|---|---|
V-01Blocking | Role and file type | Confirm an Owner or Admin ran the audience export and the download is a ZIP or a single CSV. | Subscribed contacts are in their own file. | Export history. | |
V-02Blocking | Other CSVs kept out | Compare filenames with Mailchimp's contact types. | Unsubscribed, cleaned, and non-subscribed files are archived and not uploaded. | File list. | |
V-03Blocking | Review step | Read Ghost's subscriber count before you confirm. | It matches the subscribed CSV row count, minus a header. | Ghost review screen. | |
V-04Blocking | Newsletter membership | Diff imported emails against members who existed yesterday. | Each existing member is on the newsletters you intended. True did not silently add them. | Diff sheet. | |
V-05Blocking | No accidental unsubscribe-all | Search the CSV for subscribed_to_emails false. | Every false row is a person who should leave every newsletter. | CSV filter. | |
V-06 | Quoted labels | Open a few imported members when you used the CSV. | Labels match the quoted column. | Member screen. | |
V-07 | Paid ids | If you used stripe_customer_id or auto, open a paid member. | The Stripe customer is the one you expected. | Member billing. | |
V-08Blocking | Recipient count | Read the count on the next issue before sending. | It matches the people who should receive that newsletter. | Send screen. |
Remove the scaffolding safely.
Safe after: One Ghost issue went to the right members, and the Mailchimp ZIP is stored outside Mailchimp.
- Keep Mailchimp from sending new campaigns.
- Store the suppression CSVs with the migration notes.
- Download anything still only in Export history before day 30.
- Rebuild the posts you still need, because content did not import.
- Leave the Mailchimp login in place until the rollback window ends.
- Schedule a review of Ghost newsletter defaults for the next import.
When the plan met reality.
First-hand accounts are preferred. Vendor case studies are labeled, and every note below is an editorial paraphrase—follow the link for the full context.
SandorWeisz moved about 1,400 Mailchimp subscribers into a Ghost site that was already two years old, as a second newsletter. About 400 of them were already members of the first newsletter. He turned on Subscribe new members on signup so the import would opt people into the new one. Existing members were not subscribed. The next send went to 1,000 people, not 1,400. He noted that Ghost's own import docs leave existing members' preferences alone. Replies pointed at the Admin API update-member call and at gctools, which can subscribe members who share a label. He said those options looked like what he needed. He did not report that he had finished the fix.
- Diff the import against people who are already Ghost members before you rely on Subscribe new members on signup.
- Plan a second step for existing members. The import will not change their newsletter choices when they remain subscribed.
- The new-member signup setting did not add 400 existing members to the second newsletter.
- The shortfall showed up as a send to 1,000 recipients instead of the 1,400 he had imported.
Verify against the primary material.
Platform behavior changes. Check these sources and the review dates above before executing a production migration.
- Ghost: migrating from MailchimpAccessed 2026-11-04
- Ghost: import membersAccessed 2026-11-04
- Mailchimp: view or export your contactsAccessed 2026-11-04