How to redirect blog post /{slug} to /{primary_tag}/{slug}


Recently I’ve updated ghost to 3.22.2 and the layout to improve its SEO. One of the changes was the route of the blog posts. Before it was and now is

But, inside of some blog posts, I’m linking with other posts, so the url is the old one and when someone clicks, it gives a 404 (also links from google).

I’ve tried playing with redirect.json but no success.
So, how could I redirect some visitors from to ?

Thank you

There is no automated way to do this unfortunately - you would need to manually update the links, or manually write redirects for each one

Hi John, thanks for replying!

I had imagined that after searching through documentation… it’s ok! I think I can do that by using ghost API to return all posts and its primary_tags to generate a valid redirects.json file and import it!

So, I ended up creating a simple javascript script to create the redirect.json file to me!
I’ll share it here in case anyone needs it too (just remember to do the small changes to the final route)

const website = ""; // blog url. ex:
const content_api_key = ""; // get content api key in: website/ghost/#/settings/integrations

// check if any tag has #fr
function hasFrTagInTags(tags) {
	for (const tag of tags) {
		if (tag.slug === "hash-fr") return true;

	return false;

// get all posts
async function getPosts() {
	const response = await fetch(
	const jsonResponse = response.json();
	return jsonResponse;

	.then((allPosts) => {
		allPosts = allPosts.posts;

		const finalJson = [];
		for (const post of allPosts) {
			const primary_tag = post.primary_tag;
			const post_slug = post.slug;

            // primary_tag is mandatory for new url structure, so if post doesn't have it, return an error showing which post miss tag
			if (!primary_tag)
				return console.error("post without primary_tag", post);

			let toUrl = "/";
           // French posts needs to append /fr/ before
			if (hasFrTagInTags(post.tags)) toUrl += "fr/";
           // final redirec url
			toUrl += `${primary_tag.slug}/${post_slug}`;

				from: `^\\/${post_slug}(\\/?)$`,
				to: toUrl,
				permanent: true,

For more details on the script, I’ve created a blog post: