Check if Drupal provides data
The assumption is that you already have a Drupal site running the latest version of Rocketship install profile or a similar setup. We also assume that you have a Next.js website running already that gets its data for a node page from JSON:API. If you do not yet, we recommend you get started with the documentation provided here.
The first step is making sure that Drupal actually provides the data on the JSON:API rest endpoint. By default the metatag property will be null:
{
jsonapi:
{
version: "1.0",
meta:
{
links:
{
self:
{
href: "http://jsonapi.org/format/1.0/"
}
}
}
},
data:
{
type: "node--page",
id: "cdbca976-6504-4b0a-8f66-e8fbc02fa2d3",
links:
{
self:
{
href: "https://dropsoliddxp.docker.localhost:444/jsonapi/node/page/cdbca976-6504-4b0a-8f66-e8fbc02fa2d3?resourceVersion=id%3A1551"
}
},
attributes:
{
drupal_internal__nid: 42,
drupal_internal__vid: 1551,
langcode: "en",
revision_timestamp: "2022-09-22T15:26:58+00:00",
revision_log: null,
status: true,
title: "Why Dropsolid",
created: "2021-10-08T14:47:34+00:00",
changed: "2022-09-22T15:26:58+00:00",
promote: false,
sticky: false,
default_langcode: true,
revision_translation_affected: true,
breadcrumbs:
[
{
uri: "internal:#",
title: "Why Dropsolid",
options: [ ]
}
],
metatag: null,
node_keeper: false,
alias_keeper: false,
keeper_machine_name: null,
path:
{
alias: "/why-dropsolid",
pid: 49,
langcode: "en"
},
publish_on: null,
unpublish_on: null,
content_translation_source: "und",
content_translation_outdated: false,
field_description: "We believe that with an open DXP you can have it all. Freedom, flexibility and peace of mind. All while still using your own stack. Learn more!",
field_meta_tags: null,
field_page_display_canonical: [ ],;
Partial output of https://example.com/jsonapi/node/page/[some-uuid]
Expose the metatag
Luckily some people have been trying to make it work. When you apply the following patch, you can expose the meta tag data.
The patch adds a computed field to certain entities called metatag_computed. This field will generate the structure for the metadata when the entity is requested. To make the data available on the entity a normalizer is used.
It will look like the following:
{
jsonapi:
{
version: "1.0",
meta:
{
links:
{
self:
{
href: "http://jsonapi.org/format/1.0/"
}
}
}
},
data:
{
type: "node--page",
id: "cdbca976-6504-4b0a-8f66-e8fbc02fa2d3",
links:
{
self:
{
href: "https://dropsoliddxp.docker.localhost:444/jsonapi/node/page/cdbca976-6504-4b0a-8f66-e8fbc02fa2d3?resourceVersion=id%3A1551"
}
},
attributes:
{
drupal_internal__nid: 42,
drupal_internal__vid: 1551,
langcode: "en",
revision_timestamp: "2022-09-22T15:26:58+00:00",
revision_log: null,
status: true,
title: "Why Dropsolid",
created: "2021-10-08T14:47:34+00:00",
changed: "2022-09-22T15:26:58+00:00",
promote: false,
sticky: false,
default_langcode: true,
revision_translation_affected: true,
breadcrumbs:
[
{
uri: "internal:#",
title: "Why Dropsolid",
options: [ ]
}
],
metatag:
[
{
tag: "link",
attributes:
{
rel: "canonical",
href: "https://dropsoliddxp.docker.localhost:444/jsonapi/node/page/cdbca976-6504-4b0a-8f66-e8fbc02fa2d3"
}
},
{
tag: "link",
attributes:
{
rel: "shortlink",
href: "https://dropsoliddxp.docker.localhost:444/node/42"
}
},
{
tag: "meta",
attributes:
{
name: "referrer",
content: "origin"
}
},
{
tag: "meta",
attributes:
{
name: "rights",
content: "©2023 Dropsolid.io. All rights reserved."
}
},
Partial output of https://example.com/jsonapi/node/page/[some-uuid]
Rebuild cache
Don’t forget to rebuild your cache in Drupal after applying the patch. Now that we have this data we can make sure that our Next.js application is showing this data so it can be picked up by search engines.
We’ll start by adding a Head component to the component that has the entity data. In our starter kit, that would be the [...slug].tsx. If you want to read more about the Head component, do check here.
…
import Head from "next/head";
export default function EntityPage({
entity,
additionalContent,
menus,
}: EntityPageProps) {
return (
// Add your metatags here
{entity.type === 'node--page' && (
)}
);
}
Partial code of [...slug].tsx
Create a separate component
You could add the metatags here manually or write some code to loop over the output, instead we’ll make a separate component to render the tags.
In my case, I’ve named the component EntityMetatags and it takes an array of metatags exactly as Drupal provides them to us through the API.
import * as React from "react";
export function EntityMetatags({ metatags, ...props }){
return (
<>
{metatags.map((metatag,index) => {
const Tag = metatag.tag
// Check if we are dealing with a normal tag or structured data.
if(!metatag.attributes?.schema_metatag){
return
}
})}
);
}
Full code of entity–metatags.tsx
Dynamically create tags
In this component we loop over the metatags that are provided and we dynamically create tags with their attributes. The metatags array also contains the schema.org metadata that can’t be added as a meta tag. At the end of the blog post we’ll talk a bit more about how you would go about doing that.
So now to actually render the metatags in your next.js application just add your newly created component to the Head component.
…
import Head from "next/head";
export default function EntityPage({
entity,
additionalContent,
menus,
}: EntityPageProps) {
return (
{entity.type === 'node--page' && (
)}
);
}
Partial code of [...slug].tsx
When you open the website in the browser and inspect our code you should see the meta tags that are configured in Drupal in the head of your Next.js application:
Some considerations when implementing this
SEO-wise you are fully covered when Next.js is running in Server side rendering mode. On the initial load of the page, the DOM will contain these metatags so the search bot doesn’t have to make additional passes to execute your JavaScript.
You’ll see that some of the data contain URLs. In some cases, you’d want to show the domain of your Next.js application instead of your Drupal application. We recommend either configuring your default tags to match this front-end domain or, in case of a multisite, using a token in Drupal with additional logic or rewriting the domain in your front-end application.
For the schema.org metadata, you currently need to rebuild the JSON output based on what was passed. If you are interested to see how we did that, do leave a comment via the contactform.
We can already give you a tip: don’t use the Next/Script component in Next/Head component. Rather use the strategy property of the Script component to get the script tag printed in the head of your Next.js application. If you want to read more about the Script component do check here.
Do come back in the future as we bring out more of these articles.