Migrating from Ghost to Substack by Migrating from Ghost to WordPress
Here's how I managed to migrate my site from Ghost to Substack by partly migrating it from Ghost to WordPress.
![Migrating from Ghost to Substack by Migrating from Ghost to WordPress](/content/images/size/w1200/2023/12/photo-1500989145603-8e7ef71d639e.jpg)
Itâs been a tough few months for Mania Inc. as we got into headwinds with Ghost CMS over payments for the Ghost Pro hosting service. My site was unfortunately, taken offline as a result, and as per the circumstances at the time, I couldnât come up with the fees to see it come back online. At the same time, I had been mulling about bringing Mania Inc. over to Substack but wasnât sure. These events then incentivized me to move my entire 650+ posts to Substack and hereâs how I did it.
Migrating from Ghost to Substack
It was time to pack up and leave Ghost. Problem is, my site was offline and the most recent export I had made from within the Ghost dashboard was from June 6th 2023, even as my site was taken offline on June 29th. As such, when I came to import my site on Substack in Settings » Import, I couldnât call on the site first via the URL to then be taken to where Iâd upload my .json export.
Saved by RSS
Luckily, I had created an RSS feed via Google Feed Burner for my site and I was able to use that feedâs url on Substack which then took me to the upload part where I could upload my .json export from Ghost. For some reason, the June 6th backup wasnât uploading, forcing me to upload an earlier backup with fewer posts; about 536 to be exact. I still needed to find a way to bring the rest of the posts over to Substack and hereâs where WordPress came in.
Migrating from Ghost to WordPress
I realized that I could use the .json export of my posts and upload it to a new/blank WordPress site and then migrate the posts I needed from WordPress to Substack. Hereâs how I did it.
Finding a WordPress Host
I needed a new and blank WordPress site to effect my import. I tried one of the free WordPress hosts but was quickly disappointed by bandwidth limits and overall slowness. As such, I opted for a Cloudways plan that would ensure that I got a robust WordPress site that I could import my Ghost export file to, and then export the posts to Substack. Cloudways offers flexible plans and I was able to quickly open a new server and install a new WordPress app on it.
PS: You can get a Cloudways plan via our link and also by using the coupon code "MANIAINC". Dreamhost would also serve the purpose. Get it here.*
*We may earn a commission but youâll get a discount.
How to Import a Ghost CMS .json Export File to WordPress
I needed a plugin to import posts from my .json export file from Ghost and to upload them into WordPress. After some research, I came accross the âGhost Importerâ plugin which was a one-click solution to import posts from a .json Ghost backup file into WP.
![WP Add New Plugin Ghost Importer](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2faaff0172-df7b-4615-ac55-65cf7d74f12c_1365x694-1.png)
I then went about installing the plugin to WP and after activating it, navigated to its UI via Tools » Ghost Importer.
![WP Tools Tab](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f70175d3d-adf8-488c-a8c0-f2e82305a0bb_1364x648-1.png)
There, the plugin asked for the Ghost siteâs URL, which I didnât have, as my site had been taken off the web. The plugin says that it needs the URL to import the images from the Ghost site.
Above, I then found a box where I could upload my .json export file. I left the site URL part blank and did not tick âPerform a dry runâ and uploaded my export file from Ghost and clicked âImportâ.
![WP Ghost Importer Select File and Input Ghost URL](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fda3c2ccd-51e3-4594-bcc5-b81ff2c06416_1366x694-1.png)
After a few minutes or so, the plugin told me that the import was successful and that it had imported 663 posts.
![Ghost Importer Plugin Import Completed and Posts Added](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fcc689165-a9b6-483e-8765-08e2b320273a_1365x695-1.png)
This was great but I only needed less than 150 posts as the rest I had imported to Substack already.
To ensure that I only got the posts I needed ready for the move to Substack, I went about deleting the 536 I had already managed to import to Substack and leave only the rest that I needed to move over.
I quickly deleted the 536 posts and left only 127 that I needed to move over to Substack. After doing this, I then went to Tools » Export and exported by WordPress site, downloading a .xml export of my WordPress site.
![Choose what to Export in Wordpress Export](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f67da0022-b7bf-41ae-9d54-5a420ddf0df6_1353x691-1.png)
![Download Exported XML file](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f5957f740-57c0-4d71-9194-0402a0734fb3_1366x652-1.png)
After doing so, I went back to Settings » Import on Substack and entered the WordPress appâs url, that led me on to the upload part.
![Copy Wordpress URL and Paste in Import Posts in Substack](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f485d4ed1-3be4-4143-9844-8d882d3f376d_1364x164-1.png)
![Enter WP URL in Substack Import Posts](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fded78bda-e51e-4192-8747-665dd429dc82_603x485-1.png)
Here, I uploaded the .xml export I got from WordPress and after a moment, Substack asked me to confirm that I am the owner of the site which I did.
![Confirm Ownership and Let Substack Import your Posts](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f05d842d5-defb-49f5-ba89-20731ed76ce6_587x451-1.png)
My 127 posts were then imported into Substack successfully.
![Posts Imported Backend](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f50df8057-c3a7-41f6-9db8-6f3a97a6c9e3_1365x692-1.png)
![Posts Imported into Substack](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fdfb04cba-601d-4f06-b376-5584a90f9ccc_1366x652-png-1.jpg)
Post-Import Editing
After importing my now 663 posts to Substack, I realized that most posts had most of their pictures broken, especially the images I had uploaded to my Ghost site. The reason for this was that my site was offline while I undertook the import to Substack and therefore, Substack was unable to fetch the images as the image links were broken, prompting an âimage not foundâ error for most images.
The images that were okay were the ones I had sourced from Unsplash within the Ghost editor. These were readily available for Substack to fetch, as Unsplash is still online and wasnât affected after my site was taken offline. There were also images available here and there within posts, with most broken and only showing the imageâs alt text as I had previously written in the alt text box in Ghost.
For the posts I imported from WordPress, all of the âFeatured Imagesâ were unavailable as I had not provided a link in Ghost Importer when importing my .json Ghost export file during the import to WordPress. Some of the images within posts were, however, present in the imported posts.
Recovering Lost Images
To recover the lost images, I had luckily gotten a link to download the backup of my Ghost site from their support staff. I therefore, had a 600+ MB backup of my site that included a folder with images.
To know which image to upload where, I would go on to open two windows/tabs of a certain post on Substack and on one press âEdit Postâ on the 3-dot dropdown menu at the top of the post, with the other window as a reference guide to where the postâs images are supposed to be.
To fetch the filename of the broken images as was in the Ghost database, I would scroll over the broken post placeholder and see the filename of the image as the end part of its URL. I would then open âFile Explorerâ on my PC with the images folder open (from the backup I downloaded that was provided by Ghost Support). I could then go on to search for that filename in that folder, and see the picture I need to upload to that particular post.
![Searching for Images in 'images' folder in the Ghost backup file](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fdc096858-d1ec-40a4-9132-66ce74500c6a_749x456-1.png)
What I Noted: Broken Elements After Import
Broken Images
For the broken images within posts i.e. except the featured image (also broken), when an image broke, it would often take off a chunk of text below where the image is in the Substack editor screen and therefore, I had to use the second window of the post (as rendered in the Substack front-end) to see if there was any text that had been cut off in the Editor screen.
![Broken Image in Imported Post](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fd1f35d90-c70f-475e-9159-fe97d5220882_1366x658-png-1.jpg)
Ghost Image Compression
In the âimagesâ folder from the backup Ghost sent me, I also realized that there were different version of each image, with the original one having â_oâ appended at the end of its filename. What this suggests is that Ghost would use some form of compression for each image uploaded within the Ghost editor, and keep both the original and compressed file.
I opted to go with the compressed images, as these were smaller in size but still had somewhat good quality. The rationale for this is that I would try to benefit from this compression of images and ensure the images I upload to Substack are already compressed and have smaller file sizes to help in ensuring that huge images do not slow down my Substack. (Not to say that they would; but better to be safe than sorry :)
Broken Embeds
Embeds that I had included in my posts in Ghost were also broken as they linked to posts that were only available in my Ghost site, denoted with a /GHOST_URL/ within the URL.As such, I needed to remove the links (which appeared as worded links in the Substack editor) and go on to paste the Substack link to that post, which embedded the posts from within Substack.
![Broken Embeds in Imported Post](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f84d144ee-5eab-4175-9792-c6670104284f_1366x559-png-1.jpg)
Author Name
Another thing I noted is that when I imported the posts from WordPress to Substack, the postsâ author was the name of the WordPress admin for that site, which at the time was âMusicâ i.e, the name of the owner of that WordPress site as set within the WP dashboard. Therefore, for the 127 posts I had imported to Substack via WordPress, I needed to remove the âMusicâ author name in the byline and replace it with my name. I did this in the Substack Editor, where I removed the âMusicâ author name and clicked on âChoose Authorâ and my name, denoted âOwnerâ was available for me to select.
![Posts Imported Author](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f630566b2-5f99-4f24-98b5-21f5e5f589de_1366x365-1.png)
I also went to Settings » Publication Details and removed the âMusicâ team member (author). You can also do this if you note a disparity with the imported authors and the ones you have on Substack.
![Change Team Members in Substack Settings](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fbaa6ca18-ea96-4534-a2a2-6baecf6ca429_1365x693-1.png)
To be on the safe side, ensure that you edit your name in the WordPress Dashboard before exporting your posts and importing them to Substack.
Missing Subtitles
âSubtitlesâ, which are the little summaries that appear below the postâs heading in Substack, were also missing for the 127 posts I migrated from WordPress to Substack; and I also had to replace those.
Missing YouTube Embeds
YouTube embeds were also missing in the Substack editor but could be seen on the unedited postâs front-end. As such, it was just a matter of simply copying the link to the video in my second (reference) window/tab of the post and noting where it was and then pasting it. This way, it could appear again after editing and not get lost as it would have had I not done this.
Broken Tweets and Instagram Embeds
Within Substack, Tweets that I had embedded in Ghost only appeared as Block Quotes in Substack and also in the editor. The same was true for Instagram posts and I chose to leave these as they were and now they can be seen as Block Quote text, with links to the posts in both the Substack frontend and backend.
Block quotes look like this sentence and can be created in the Substack Editor.
![Posts Imported Tweet](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f6b46ac76-8f05-4f73-aa49-8c27be08b319_1366x694-1.png)
Broken Featured Image and Previews
Most of the posts I imported to Substack had their feature images broken and I had to replace these. To ensure that post previews, which were also broken, showed the images I had now uploaded, I went to Substack Editor » Continue » Social Preview and selected the new image. The social preview also acts the âthumbnailâ or the post preview image and this sorted both.
URLs Retained
The good thing, however, is all my posts retained their url i.e, the end part of it. This means that instead of https://maniainc.com/post-url they were now https://maniainc.substack.com/p/post-url.. note the /p/ which is part of the standard post url for all substacks i.e subdomain.substack.com/p/post-url.
![Posts Imported URL](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fda0ba0b2-5f14-4763-81ef-97f751af4683_1366x243-1.png)
Redirecting Ghost Post URLs to Matching Substack Post URLs
To ensure that all my previous Ghost URLs for posts redirected to the particular posts on Substack, I leveraged Cloudflareâs Page Rules to help create dynamic URLs via wildcards. I went to Cloudflare Dashboard » Rules » Create a Page Rule and input the following.
In the URL box I input *.maniainc.com/*
For the Setting I selected âForward URLâ and Status Code â302 - Temporary Redirectâ
For the destination Url, I input https://maniainc.substack.com/$1/$2
I also selected Priority as âFirstâ meaning that this rule is the first to trigger in Cloudflare Rules. You can also do this by dragging the rule to be the first in Page Rules.
![Cloudflare Redirects](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2fbc583a89-003a-4b5f-a144-204820307980_1364x650-1.png)
By doing this, I essentially told Cloudflare that for any URL with a matching path after the main domain name and first /, it should redirect it to my Substack URL and look for two wildcard matches denoted $1 and $2 which are glob patterns for wildcards. For in-depth understanding, read more about referencing wildcard matches on Cloudflare.
Long story short, any Ghost URL that points to a post now redirects to that particular post in Substack as the first glob ($1) considers Substackâs /p/ url part for every pattern and then the second glob ($2) considers the matching part of the link which is the last part of the post url. As such, maniainc.com/post-url now redirects to maniainc.substack.com/p/post-url. Remember to replace maniainc.com and maniainc.substack.com with the actual domain name of your site and your Substack subdomain name respectively.
Please Note:
- I already have rules in Cloudflare that point www.maniainc.com to maniainc.com and one that redirects maniainc.com to maniainc.substack.com.
- I had also added a custom domain in Ghost which was maniainc.com and therefore, I am not using my Ghost URL which is usually sub-domain.ghost.io. If you hadnât, you can use your Ghost url in place of the custom domain to create the redirects and for the purposes of this entire guide.
- This approach may not work for internal links within the imported posts as they had already had /GHOST_URL/ appended within them by Ghost as noted earlier.
Editing All Imported Posts
I then repeated the process of opening two windows for each post that I saw had broken images within the body of the posts, replacing said images and recovering any text that wasnât showing in the editor that had been âchunkedâ away. I also went on to replace any internal links I had within the posts, replacing them with Substack links to those posts.
Restricting Access to Paid Subscribers Only in Substack
I also included the Paywall marker to show what part of the post would only be available to Paid Subscribers. You can do this by going to Substack Editor » More and choosing â$ Paywallâ in the drop down menu.
Categorizing Imported Posts
I also choose to introduce Sections and categorize my posts in a way that users can choose to only receive emails regarding only those posts that are in a particular section. Sections are essentially categories in Substacks and readers can choose to only receive emails on posts in particular sections.
How to Add New Sections in Substack
You can add a new section by going to Settings » Sections in Substack and you can put a post in a particular section by going to Edit Post and then choosing a section from the dropdown menu just above the post title or by going to Continue » This post belongs to.. and choosing a section.
A List of all the Edits Made
Hereâs the entire list of the edits I needed to make to retain my posts as they were on Ghost:
- Replace broken images.
- Recover unrendered text in the Substack editor that had been chunked off.
- Edit Author where necessary.
- Enter a Subtitle where itâs missing.
- Choose a section for the post.
- Replace broken embeds.
- Replace missing YouTube embeds.
- Introduce the $ Paywall marker.
- Replace the Social Preview Image.
Relief
After two to three days of intense editing, as I had 663 posts to edit, I finally managed to edit all my posts and ensure that I got the import as robust as it could be. For the posts imported from WordPress that had no featured images, I choose to leave them as such, as Substack will automatically pick the first image in a post to be the social preview and or thumbnail for the image. All I had to do was go to Continue in the Substack Editor and choose an image from within the post to be my social preview image.
Customizing my Substack Site
I then went about customizing the look of my Substack site, which I did by going to Settings » Website » Site Design. I am super happy with how the move turned out, albeit having to put in some work to ensure it was as smooth as possible. The site I moved is this site you are reading: https://maniainc.com and I am elated to be on Substack.
![How Mania Inc. looks today](https://mania.africa/content/images/2023/12/https-3a-2f-2fsubstack-post-media-s3-amazonaws-com-2fpublic-2fimages-2f9bb4d61d-47a4-49d6-bd83-b8e4af5b6c67_1365x693-png-1.jpg)
I hope this post has helped you migrate from Ghost to Substack via or even from WordPress to Substack.
» This post is free and if you liked it, consider subscribing to this website and the âDevelopersâ newsletter in particular.«
You can also support us on Patreon or buy us a coffee via PayPal. Thanks.