8/14/2023 4:10:21 PM

When working with React, whether using standard links or using the React Router Link component, you will want to set unique page meta data. This includes the Title, Description, Keywords, Canonical Url, and Image Url. This is, of course, extremely important to improve user experience and SEO. I still do not fully trust Google and other search engines from indexing React sites but we have to do our part.

The following code updates the meta data for your site. You can either import and use the individual methods (meta_set_title, meta_set_description, etc) or you can use the meta_set function and pass all values in as an object. The code uses TypeScript. If you are not using TypeScript, you can simply remove the variable type declarations (ex: change "title: string" to "title"). The code does not rely on any external packages or frameworks. It uses simple JavaScript.

export function meta_set(meta_data: any) { //console.log("meta_set", meta_data); //meta_data = {title: "", description: "", keywords: "", url_path: "", image_url: ""} meta_set_title(meta_data.title); meta_set_description(meta_data.description); meta_set_keywords(meta_data.keywords); meta_set_canonical_url(meta_data.url_path); meta_set_image_url(meta_data.image_url); } export function meta_set_title(title: string) { //console.log("meta_set_title"); if (!title) { //we could set this to an emtpy string title = ""; //or just return return; } document.title = title; head_add_update_tag("meta", "name='title'", "content", title); head_add_update_tag("meta", "property='og:title'", "content", title); head_add_update_tag("meta", "name='twitter:title'", "content", title); } export function meta_set_description(description: string) { //console.log("meta_set_description"); if (!description) { description = ""; } head_add_update_tag("meta", "name='description'", "content", description); head_add_update_tag("meta", "property='og:description'", "content", description); head_add_update_tag("meta", "name='twitter:description'", "content", description); } export function meta_set_keywords(keywords: string) { //console.log("meta_set_keywords"); if (!keywords) { keywords = ""; } head_add_update_tag("meta", "name='keywords'", "content", keywords); } export function meta_set_canonical_url(url_path: string) { //console.log("meta_set_canonical_url"); if (!url_path) { url_path = ""; } let url = ""; url = location.protocol + '//' + location.host; if (url_path.startsWith("/") === false) { url += "/"; } url += url_path; head_add_update_tag("link", "rel='canonical'", "href", url); head_add_update_tag("meta", "property='og:url'", "content", url); } export function meta_set_image_url(image_url: string) { //console.log("meta_set_image_url"); if (!image_url) { image_url = ""; } head_add_update_tag("meta", "property='og:image'", "content", image_url); head_add_update_tag("meta", "name='twitter:image'", "content", image_url); } function head_add_update_tag(tag: string, selector: string, property: string, value: string) { //get current element let element: any = document.querySelector(`${tag}[${selector}]`); if (element) { //if exists, set value element.setAttribute(property, value); } else { //if it doesn't exist, create it and add it to the document element = `<${tag} ${selector} ${property}="${value}" />`; document.head.insertAdjacentHTML("beforeend", element); } }