diff --git a/package.json b/package.json
index 71be12f4271..e3fa035a517 100644
--- a/package.json
+++ b/package.json
@@ -14,10 +14,11 @@
"build:compress": "./scripts/build.compress.sh",
"build:csp": "node scripts/build.csp.mjs",
"build:metadata": "node scripts/build.metadata.mjs",
+ "build:seo": "node scripts/build.seo.mjs",
"build:style": "node scripts/build.style.mjs",
"build:ic-domains": "node scripts/build.ic-domains.mjs",
"build:ii-alternative-origins": "node scripts/build.ii-alternative-origins.mjs",
- "build:post-process": "npm run build:style && npm run build:metadata && npm run build:ic-domains && npm run build:ii-alternative-origins && npm run build:csp && npm run build:compress",
+ "build:post-process": "npm run build:style && npm run build:metadata && npm run build:seo && npm run build:ic-domains && npm run build:ii-alternative-origins && npm run build:csp && npm run build:compress",
"build:tokens-sns": "vite-node scripts/build.tokens.sns.ts && npm run format:file --file=src/frontend/src/env/tokens/tokens.sns.json",
"build:tokens-ckerc20": "vite-node scripts/build.tokens.ckerc20.ts && npm run format:file --file=src/frontend/src/env/tokens/tokens.ckerc20.json",
"build:tokens-icrc": "vite-node scripts/build.tokens.icrc.ts && npm run format:file --file=src/frontend/src/env/tokens/tokens.icrc.json",
diff --git a/scripts/build.seo.mjs b/scripts/build.seo.mjs
new file mode 100644
index 00000000000..5607dba04c8
--- /dev/null
+++ b/scripts/build.seo.mjs
@@ -0,0 +1,38 @@
+import { readFileSync, writeFileSync } from 'node:fs';
+import { dirname, join, relative } from 'node:path';
+import { OISY_IC_DOMAIN, findHtmlFiles } from './build.utils.mjs';
+
+const OUTPUT_DIR = join(process.cwd(), 'build');
+const SITE_ROOT_CANONICAL = OISY_IC_DOMAIN;
+
+const updateCanonical = (htmlFilePath) => {
+ // 1. We determine the route based on the output
+ const routePath = dirname(relative(OUTPUT_DIR, htmlFilePath));
+
+ // 2. Build the effective canonical route
+ const canonicalPath = `${SITE_ROOT_CANONICAL}/${routePath}/`;
+
+ // 2. Read content
+ let html = readFileSync(htmlFilePath, 'utf-8');
+
+ // 3. Update canonical
+ html = html.replace(
+ ``,
+ ``
+ );
+
+ // 4. Update og:url to reflect the canonical
+ html = html.replace(
+ ``,
+ ``
+ );
+
+ // 5. Save the content with the updated canonical URL
+ writeFileSync(htmlFilePath, html);
+};
+
+// Do not replace canonical for root and 404 pages
+const filterSubPages = (htmlFile) => dirname(htmlFile) !== OUTPUT_DIR;
+
+const htmlFiles = findHtmlFiles().filter(filterSubPages);
+htmlFiles.forEach(updateCanonical);