Astro: Extracting Common Meta Tags Into a Separate File
At the start of creating a content site, you usually have one or two layouts, but after some time, you’ll likely add more. All of these layouts share common metadata, usually located in layout’s <head>
tag.
It’s possible to manage all of that metadata inside each page separately, but that might quickly turn into a mess. Imagine you want to update analytics, or add a new metatag for SEO. Updating each and every layout will require more time and might lead to errors.
In line with the DRY principle ↗, let’s put that metadata inside a separate file and use it across all our pages and layouts.
Create a common metadata file
First, we will need to create a file that will contain all common metadata. I usually call that file HeadBase.astro
and put it inside includes
directory (to separate it from components, pages, and layouts).
It’s up to you what should belong to that “include”, but in general, stuff like SEO and social tags, favicon, common styles, and analytic scripts belong there.
If you’ll need some data from the page that will use that file, add necessary props to the HeadBase
.
Here’s an example of such file. Note that it has two props, one of which is optional:
---
import './styles/global.css'
const { title, description = '' } = Astro.props;
---
<!-- Global Metadata -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="title" content={title} />
{description && <meta name="description" content={description} />}
<!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:title" content={title} />
{description && <meta property="og:description" content={description} />}
<!-- Twitter -->
<meta property="twitter:card" content="summary" />
<meta property="twitter:title" content={title} />
{description && <meta property="twitter:description" content={description} />}
Use the file inside layouts and pages
Now that we created an include file, we can use it inside our pages and layouts:
---
import HeadBase from '../includes/HeadBase.astro';
const { content } = Astro.props;
const { title, description } = content;
---
<html>
<head>
<HeadBase {title} {description} />
</head>
<body>
<div>Content</div>
</body>
</html>
Update the file
The beauty of such pattern is that it enables us to update any part of the common metadata by updating our HeadBase
file.
Let’s say we want to add another global stylesheet. We just need to add a new <link>
at the bottom of the HeadBase.astro
file. This will add that stylesheet to all pages.
Another option is adding common functionality to the pages. Let’s extend the include by adding a new optional url
prop which will be used to generate social tags:
---
const { title, description = '', url = '' } = Astro.props;
---
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
{url && <meta property="og:url" content={url} />}
<meta property="og:title" content={title} />
{description && <meta property="og:description" content={description} />}
<!-- Twitter -->
<meta property="twitter:card" content="summary" />
{url && <meta property="twitter:url" content={url} />}
<meta property="twitter:title" content={title} />
{description && <meta property="twitter:description" content={description} />}
Now we can pass the new prop into one of the pages:
<html>
<head>
<HeadBase {title} {description} {url} />
</head>
</html>
Since the prop is optional, we don’t need to update unaffected pages.