facebook / docusaurus

Easy to maintain open source documentation websites.
https://docusaurus.io
MIT License
55.31k stars 8.29k forks source link

Injecting dynamic meta tags into every page source #3501

Closed danielabbasi closed 3 years ago

danielabbasi commented 3 years ago

❓ Questions and Help

Problem

We have a private search service scraper that needs to scrape every page and find information in the meta tag where the content changes based on location. The logic for the dynamic content is currently in a custom hook and it uses window.location.pathname. This scraper is not using chrome headless therefore it can only see the source of the page ('view source' in chrome rather than 'inspect element').

Solutions we have tried

  1. Use theme Layout component to pass dynamic content into meta tag within Head. This worked great when using 'inspect element' which does some client side rendering but the meta tag do not appear in the actual source of the page.

  2. Use injectHtmlTags to inject the meta tags however this injects a static meta tag without dynamic content into every page. It did however appear in the source. Not sure if I can get dynamic content in there based on the location? Couldn't find any documentation.

  3. Similar to docusaurus-plugin-google-analytics approach we have attempted to use onRouteUpdate which I understand is currently a hidden feature. We however are not sure how to inject dynamic meta tags within onRouteUpdate so any help would be appreciated.

Posting on here after talking about this on the discord channel for visibility as this may become a problem that other users need to solve.

Any help on the best approach to solve this problem is appreciated :smile:

Docusaurus Version

"@docusaurus/core": "2.0.0-alpha.48", "@docusaurus/preset-classic": "2.0.0-alpha.48",

slorber commented 3 years ago

Hi,

First I'd suggest to upgrade to latest version.

As you need a HTML scrapper to see the meta tag, it has to be server-side rendered at build time, and be found in built HTML files. What I understand is that your scrapper does not run the ReactJS code, so you can't set the value using JS on client-side.

Here's how I was able to get this working, by wrapping the default layout component to "enhance" it with additional logic, so that all the pages of your site would have this additional logic (as long as they all use the default layout).

https://v2.docusaurus.io/docs/using-themes/#wrapping-theme-components

Put this in src/theme/Layout.js:

import React from 'react';
import OriginalLayout from '@theme-original/Layout';
import Head from '@docusaurus/Head';
import {useLocation} from '@docusaurus/router';

export default function Layout(props) {
  const location = useLocation();
  return (
    <>
      <Head>
        <meta
          property="my-custom-property"
          content={'my location value = ' + location.pathname}
        />
      </Head>
      <OriginalLayout {...props} />
    </>
  );
}

Then after a build, you should see your custom meta header appear.

For example opening this file on docusaurus site:

image

I can see it is visible here:

image

And then your scrapper should be able to read this metadata

Note: useLocation comes from react-router, read its doc for more details