Add reusable SEO component for per-page meta updates
cgen-15bd42da815c402e9d5ea00d1462eca7
This commit is contained in:
parent
160eaef805
commit
25e7e03ad0
1 changed files with 52 additions and 0 deletions
52
client/components/SEO.tsx
Normal file
52
client/components/SEO.tsx
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { useEffect } from "react";
|
||||
|
||||
export type SEOProps = {
|
||||
pageTitle: string;
|
||||
description?: string;
|
||||
image?: string | null;
|
||||
canonical?: string | null;
|
||||
noIndex?: boolean;
|
||||
};
|
||||
|
||||
function upsertMeta(selector: string, attrs: Record<string, string>) {
|
||||
let el = document.querySelector(selector) as HTMLElement | null;
|
||||
if (!el) {
|
||||
const tag = selector.startsWith('meta[') ? 'meta' : selector.startsWith('link[') ? 'link' : 'meta';
|
||||
el = document.createElement(tag);
|
||||
document.head.appendChild(el);
|
||||
}
|
||||
Object.entries(attrs).forEach(([k, v]) => (el as any).setAttribute(k, v));
|
||||
}
|
||||
|
||||
export default function SEO({ pageTitle, description, image, canonical, noIndex }: SEOProps) {
|
||||
useEffect(() => {
|
||||
const title = `AeThex | ${pageTitle}`;
|
||||
document.title = title;
|
||||
|
||||
if (canonical) {
|
||||
upsertMeta('link[rel="canonical"]', { rel: 'canonical', href: canonical });
|
||||
upsertMeta('meta[property="og:url"]', { property: 'og:url', content: canonical });
|
||||
}
|
||||
|
||||
if (description) {
|
||||
upsertMeta('meta[name="description"]', { name: 'description', content: description });
|
||||
upsertMeta('meta[property="og:description"]', { property: 'og:description', content: description });
|
||||
upsertMeta('meta[name="twitter:description"]', { name: 'twitter:description', content: description });
|
||||
}
|
||||
|
||||
upsertMeta('meta[property="og:title"]', { property: 'og:title', content: title });
|
||||
upsertMeta('meta[name="twitter:title"]', { name: 'twitter:title', content: title });
|
||||
|
||||
if (image) {
|
||||
upsertMeta('meta[property="og:image"]', { property: 'og:image', content: image });
|
||||
upsertMeta('meta[name="twitter:image"]', { name: 'twitter:image', content: image });
|
||||
}
|
||||
|
||||
if (noIndex) {
|
||||
upsertMeta('meta[name="robots"]', { name: 'robots', content: 'noindex, nofollow' });
|
||||
upsertMeta('meta[name="googlebot"]', { name: 'googlebot', content: 'noindex, nofollow' });
|
||||
}
|
||||
}, [pageTitle, description, image, canonical, noIndex]);
|
||||
|
||||
return null;
|
||||
}
|
||||
Loading…
Reference in a new issue