Public page SEO and production analytics (#125)
## Summary - Closes the public-page gaps from #124: each route gets its own title, description, canonical, heading, links, and JSON-LD, and unknown URLs have a real 404 document. - Adds HeyCatch and the Google tag (`G-V12DLRLPWR`) only on the production site and the iOS and Android apps. Tianji still loads on beta. - Needs the server-infra change that stops serving the app shell for missing paths. ## Test plan - [ ] Build production and confirm `/` and `/pricing/` HTML include a unique title, description, canonical, one h1, social tags, related links, and Organization JSON-LD. - [ ] Confirm a nonsense path is served as `404.html` once the nginx change is deployed. - [ ] Confirm beta and local web do not load HeyCatch or gtag, and that a production or native build does. - [ ] Open the live site after deploy and click around, then mark HeyCatch installed in its dashboard. Reviewed-on: #125
This commit was merged in pull request #125.
This commit is contained in:
1 parent
8b58192026
commit
7a8f413483
45 files changed
+1880
-174
No files matched your search
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* One IndexNow POST for the URLs in the sitemap. Run after the prod files are published.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { INDEXNOW_KEY, indexNowBody, sitemapEntries } = require('./sitemap');
|
||||
|
||||
async function pingIndexNow(fetchImpl = fetch, urls) {
|
||||
const keyPath = path.join(__dirname, '..', 'public', `${INDEXNOW_KEY}.txt`);
|
||||
const key = fs.readFileSync(keyPath, 'utf8').trim();
|
||||
if (key !== INDEXNOW_KEY) {
|
||||
throw new Error(`IndexNow key file does not match ${INDEXNOW_KEY}`);
|
||||
}
|
||||
const urlList = urls || sitemapEntries().map((entry) => entry.loc);
|
||||
const body = indexNowBody(key, urlList);
|
||||
const response = await fetchImpl('https://api.indexnow.org/indexnow', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
const text = await response.text();
|
||||
if (response.status !== 200 && response.status !== 202) {
|
||||
throw new Error(`IndexNow ${response.status}: ${text}`);
|
||||
}
|
||||
return { status: response.status, body };
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const result = await pingIndexNow();
|
||||
process.stdout.write(`IndexNow ${result.status}\n`);
|
||||
}
|
||||
|
||||
module.exports = { pingIndexNow };
|
||||
|
||||
if (require.main === module) {
|
||||
main().catch((error) => {
|
||||
process.stderr.write(`${error.message}\n`);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user