next.js: generateMetadata SEO doesn't work and tags not recognized

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: x64
      Version: Darwin Kernel Version 22.1.0: Sun Oct  9 20:14:54 PDT 2022; root:xnu-8792.41.9~2/RELEASE_X86_64
    Binaries:
      Node: 18.12.1
      npm: 5.1.0
      Yarn: 1.22.19
      pnpm: 7.27.1
    Relevant packages:
      next: 13.2.1
      eslint-config-next: 13.1.6
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true), Data fetching (gS(S)P, getInitialProps), Metadata (metadata, generateMetadata, next/head, head.js)

Link to the code that reproduces this issue

The repo is private

To Reproduce

Hello !

I’m using next 13.2.1 and i’m trying to get dynamic SEO metadata on server side component.

Here is my code:

export async function generateMetadata({ params }): Promise<Metadata> {
  const article = await getArticle(params.id).then(
    (res) => res.data.getArticle
  );

  return {
    title: article.title,
    description: article.description,
    openGraph: {
      title: article.title,
      description: article.description,
      images: [
        {
          url: getImageUrl(article.cover_image),
          width: 800,
          height: 600,
          alt: article.title,
        },
      ],
    },
    robots: {
      index: false,
      follow: true,
      nocache: true,
      googleBot: {
        index: true,
        follow: false,
        noimageindex: true,
        "max-video-preview": -1,
        "max-image-preview": "large",
        "max-snippet": -1,
      },
    },
    twitter: {
      card: "app" /* "summary" | "summary_large_image" | "app" | "player" */,
      title: article.title,
      site: "@airpen.cc",
      description: article.description,
      creator: "@airpen.cc",
      images: {
        url: getImageUrl(article.cover_image),
        alt: article.title,
      },
      app: {
        name: "twitter_app",
        id: {
          iphone: "twitter_app://iphone",
          ipad: "twitter_app://ipad",
          googleplay: "twitter_app://googleplay",
        },
        url: {
          iphone: "https://iphone_url",
          ipad: "https://ipad_url",
        },
      },
    },
  };
}

So there i fetch dinamicly data from a server side request and fill in the metadata as in the doc.

The fact is that when i go to the page, i see the tags being there in the <head> tag: Capture d’écran 2023-03-09 à 18 39 37

But when i paste the link in social media or wherever else, no metadata is found. I tryied to curl the URL to see what i get, and in fact, here is the answer:

<!DOCTYPE html>
<html lang="en">
  <link
    rel="stylesheet"
    href="/_next/static/css/017256b768b56c51.css"
    data-precedence="next.js"
  />
  <body class="relative">
    <script>
      !(function () {
        try {
          var d = document.documentElement,
            c = d.classList;
          c.remove("light", "dark");
          var e = localStorage.getItem("theme");
          if ("system" === e || (!e && true)) {
            var t = "(prefers-color-scheme: dark)",
              m = window.matchMedia(t);
            if (m.media !== t || m.matches) {
              d.style.colorScheme = "dark";
              c.add("dark");
            } else {
              d.style.colorScheme = "light";
              c.add("light");
            }
          } else if (e) {
            c.add(e || "");
          }
          if (e === "light" || e === "dark") d.style.colorScheme = e;
        } catch (e) {}
      })();
    </script>
    <w3m-modal></w3m-modal>
    <script
      src="/_next/static/chunks/webpack-9785447c26751819.js"
      async=""
    ></script>
    <script
      src="/_next/static/chunks/679-34054645ed5daca9.js"
      async=""
    ></script>
    <script
      src="/_next/static/chunks/main-app-e8651b63095acae0.js"
      async=""
    ></script>
  </body>
</html>
<script>
  (self.__next_f = self.__next_f || []).push([0]);
</script>
<script>
  self.__next_f.push([1, '0:"$L1"\n']);
</script>
<script>
  self.__next_f.push([
    1,
    '2:I{"id":"3395","name":"","chunks":["2272:webpack-9785447c26751819","679:679-34054645ed5daca9"],"async":false}\n4:I{"id":"8668","name":"","chunks":["2272:webpack-9785447c26751819","679:679-34054645ed5daca9"],"async":false}\n5:I{"id":"80830","chunks":["3698:caa9e9db-294e732127a2118f","2104:2104-34c077f3ca8d7003","8362:8362-50ce1b33c5f2ccdf","6394:6394-c1368f2aa5309fc8","4824:4824-3f31c22f6711a935","5437:5437-bd58837441e18dc5","9707:9707-1707c6246b257a2c","54:54-e1a05b61c9b793d6","7376:7376-226fc626b2358d7d","1',
  ]);
</script>
<script>
  self.__next_f.push([
    1,
    '93:193-90b2132be77e6317","7992:7992-1e43c188fe204dcf","6202:6202-31635e9c9663a628","7613:7613-fc110fca7a12c2c6","3185:app/layout-68a9f5ecc6bee25e"],"name":"default","async":true}\n6:I{"id":"57449","name":"","chunks":["2272:webpack-9785447c26751819","679:679-34054645ed5daca9"],"async":false}\n7:I{"id":"30485","name":"","chunks":["2272:webpack-9785447c26751819","679:679-34054645ed5daca9"],"async":false}\n8:I{"id":"11030","chunks":["6688:app/[id]/layout-4ccc19c487649b32"],"name":"default","async":true}\n9:I{"id":"',
  ]);
</script>
<script>
  self.__next_f.push([
    1,
    '59125","chunks":["2104:2104-34c077f3ca8d7003","8208:app/[id]/error-8336ef22d886e2d0"],"name":"default","async":true}\na:I{"id":"86747","chunks":["5171:app/[id]/loading-9e56ac59acf2b08f"],"name":"default","async":true}\n',
  ]);
</script>
<script>
  self.__next_f.push([
    1,
    '1:["$","$L2",null,{"assetPrefix":"","initialCanonicalUrl":"/63f63c6598ddcea746136d60","initialTree":["",{"children":[["id","63f63c6598ddcea746136d60","d"],{"children":["",{}]}]},null,null,true],"initialHead":["$L3",null],"globalErrorComponent":"$4","children":[["$","$L5",null,{"children":["$","$L6",null,{"parallelRouterKey":"children","segmentPath":["children"],"hasLoading":false,"template":["$","$L7",null,{}],"notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\\"Segoe UI\\",Roboto,Helvetica,Arial,sans-serif,\\"Apple Color Emoji\\",\\"Segoe UI Emoji\\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"childProp":{"current":[["$","$L8",null,{"children":["$","$L6",null,{"parallelRouterKey":"children","segmentPath":["children",["id","63f63c6598ddcea746136d60","d"],"children"],"error":"$9","errorStyles":[],"loading":["$","$La",null,{}],"loadingStyles":[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/1b1cf59279a9b628.css"}]],"hasLoading":true,"template":["$","$L7",null,{}],"childProp":{"current":["$Lb",null,null,[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/1b1cf59279a9b628.css","precedence":"next.js"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/css/2d19121551e6d1a9.css","precedence":"next.js"}]]],"segment":""}}],"params":{"id":"63f63c6598ddcea746136d60"}}],null,null,[]],"segment":["id","63f63c6598ddcea746136d60","d"]}}],"params":{}}],null,null,[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/017256b768b56c51.css","precedence":"next.js"}]]]}]\n',
  ]);
</script>

All the tags are completely gone and so that’s normal that neither Twitter of Facebook can’t fetch the tags to make the right previews.

But how is that possible ? Nothing related to that in the docs. I’ve been dealing with that for weeks.

Thanks 🙏

Describe the Bug

Can’t preview the page with the SEO metadata tags not working.

When i test the link on https://cards-dev.twitter.com/validator I get: Capture d’écran 2023-03-09 à 18 48 07

Expected Behavior

When i paste a link on twitter or facebook, i’d like the meta image and description showing up, but nothing work, even when SEO implemented as the doc ask to do.

Which browser are you using? (if relevant)

Arc, Chrome & Brave

How are you deploying your application? (if relevant)

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 1
  • Comments: 26 (3 by maintainers)

Most upvoted comments

Turns out using export const dynamic = 'force-dynamic'; on the root page fixes it. Also, you need to add a trailing slash / at the end of your url for it to work.

@anthonyjacquelin im encountering the same issue. Interesting tidbit: this only happens for me for the root page. The remaining pages (I have some slug urls) this is fine.

https://www.projectspce.com/brands/aersf <—works https://www.projectspce.com/ <-- doesnt work

That being said, when I tested both urls i get limited data: https://opengraph.dev/panel?url=https%3A%2F%2Fwww.projectspce.com%2Fbrands%2Faersf