Quick-search for anything
⌘F

Migrating from Substack

Migrate from Substack and import your content to Ghost with this guide

The Ghost Concierge team, at your service

Let us handle the Substack migration for you! This migration is included when you make an annual payment on the Ghost(Pro) Creator, Team, or Business plans. Learn more about the Concierge service.

Exporting your subscribers

To get started, export All Subscribers in CSV format. This exports your entire Subscriber list from Substack:

substack export

If you’re also migrating paid subscribers, you’ll need to export the Stripe ID’s of your customers by exporting the Paid Subscribers list, which downloads a separate CSV with this information included.

Now you’ll have all of the the email subscriber and customer data required to migrate from Substack to Ghost.

Import subscribers to Ghost

We recommend preparing the data in your CSV using our guide on importing members in Ghost. Alternatively, we can do this work for you with an annual payment on the Ghost(Pro) Creator, Team, or Business plans.

Once you’re happy that you subscriber data is complete, under the Ghost Admin members settings, select the import option from the settings menu.

import members

Upload your CSV file to Ghost, and map each of the fields contained in your CSV to the corresponding fields in Ghost. The email field is required in order to create members in Ghost, while the other fields are optional.

Importing paid members

To import paid members with an existing Stripe subscription, you must import their Stripe customer ID.

import members

Once the import has completed, all your subscribers will be migrated to Ghost.

Importing subscribers with a comp or gift plan

If you’ve provided any of your subscribers with a free or gifted paid access to premium content in Substack, you can also give them free access to paid content in Ghost by importing their email address with the Complimentary Plan column flagged as true in your CSV import.

This provides these members with unlimited free access to premium content on your Ghost publication with an access level of paid-members only. If you’d like your members complimentary access to expire after a specific date, the easiest way to do this is to edit the complimentary subscription directly in Stripe and schedule the date the subscription should be cancelled.

import members

Removing Substack fees

Because of how Stripe works, disconnecting will not prevent Substack from continuing to take a 10% commission on all existing subscriptions. Substack have an official policy that you can contact them before leaving to have these fees removed. Ask their support team to remove fees, unlink your Stripe account, and leave subscriptions as-is in Stripe.

Once fees have been removed, and you have completed your migration, you should ensure Substack is disconnected from Stripe to prevent subscriptions from getting out-of-sync in future. You can do this by going to https://dashboard.stripe.com/account/applications β€” and clicking on Revoke Access.

disconnect substack from stripe

Migrating Content

Developers can migrate content from Substack to Ghost using our migration CLI tools.

You will first need to export your content from Substack. This will include a file called posts.csv which includes meta data for each post, and a directory full of HTML files which contains the post content.

First, make sure the CLI is installed.

# Install CLI
npm install --global @tryghost/migrate

# Verify it's installed
migrate

To run a basic migration with the default commands:

# Basic migration
migrate substack --pathToZip export.zip --url https://mysite.substack.com

In the above example:

  • Changes subscribe links to open Portal
  • Changes comments links to link to #ghost-comments-root
  • Excludes thread posts
  • Uses the og:image value as the feature image
  • Uses the ld+json data to set the post authors

By setting some options,

# Migration with options
migrate substack --pathToZip export.zip --url https://mysite.substack.com --email '[email protected]' --drafts false --commentLink \#comments

In addition to the basic example above, this more complex example:

  • Excludes draft posts
  • Sets the post author to be [email protected]
  • Changes comment links to #comments

There are more options, such as the ability to only migrate content to and from specific dates, handling of draft posts, and more.

Once the CLI task has finished, it creates a new ZIP file which you can import into Ghost.

Using custom domains

If you’re using a custom domain on Substack, you’ll need to implement redirects in Ghost to prevent broken links.

Substack uses /p/ as part of the public post URL, where as Ghost uses it in the URL for post previews. This means the redirect regular expression is quite complex, but necessary so that post previews in Ghost function correctly.

# redirects.yaml
301:
    \/p\/(?![0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})(.*): /$1

302:

This means that if a visitor or crawler goes to https://mysite.com/p/awesome-post, they will automatically be redirected to https://mysite.com/awesome-post.


Summary

Congratulations on your migration to Ghost πŸ™Œ. All that’s left to do is check over your content to ensure the migration has worked as expected. We also have a guide on how to implement redirects to make your transition smoother.