Eleventy (11ty) Open Graph Meta Tags: Add OG to Nunjucks and Liquid
Add og:title, og:image, og:description, and Twitter card tags to Eleventy (11ty) sites using Nunjucks macros, Liquid includes, and front matter data.
Why Eleventy is OG-friendly
Eleventy (11ty) is a static site generator that builds plain HTML files at build time. There's no JavaScript runtime needed for crawlers — your OG tags are baked directly into the HTML. The challenge is making the templates dynamic enough to generate unique OG tags per page.
Eleventy supports multiple template languages: Nunjucks, Liquid, Handlebars, Markdown, and JavaScript. The examples below cover Nunjucks (most popular) and Liquid.
Base layout with OG tags (Nunjucks)
Create a base layout in _includes/base.njk with dynamic OG tag variables:
{# _includes/base.njk #}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title or metadata.title }} | {{ metadata.title }}</title>
{# Open Graph #}
<meta property="og:title" content="{{ title or metadata.title }}" />
<meta property="og:description"
content="{{ description or metadata.description }}" />
<meta property="og:image"
content="{{ ogImage or metadata.url + metadata.defaultOgImage }}" />
<meta property="og:url"
content="{{ metadata.url + page.url }}" />
<meta property="og:type"
content="{{ ogType or 'website' }}" />
<meta property="og:site_name"
content="{{ metadata.title }}" />
{# Twitter Card #}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="{{ title or metadata.title }}" />
<meta name="twitter:description"
content="{{ description or metadata.description }}" />
<meta name="twitter:image"
content="{{ ogImage or metadata.url + metadata.defaultOgImage }}" />
</head>
<body>
{{ content | safe }}
</body>
</html>Global data in _data/metadata.json
// _data/metadata.json
{
"title": "My Eleventy Site",
"description": "My site description.",
"url": "https://example.com",
"defaultOgImage": "/images/og-default.jpg",
"twitterHandle": "@yourtwitterhandle"
}Per-page OG tags in front matter
--- title: My Blog Post description: A description specifically for this blog post. ogImage: /images/posts/my-post-og.jpg ogType: article layout: base.njk date: 2026-03-15 --- # Post content here
Liquid template version
For Liquid templates, the syntax is slightly different:
{# _includes/og-tags.liquid #}
{% assign og_title = title | default: metadata.title %}
{% assign og_desc = description | default: metadata.description %}
{% if ogImage %}
{% assign og_img = ogImage | prepend: metadata.url %}
{% else %}
{% assign og_img = metadata.defaultOgImage | prepend: metadata.url %}
{% endif %}
<meta property="og:title" content="{{ og_title | escape }}" />
<meta property="og:description" content="{{ og_desc | escape }}" />
<meta property="og:image" content="{{ og_img }}" />
<meta property="og:url" content="{{ page.url | prepend: metadata.url }}" />
<meta property="og:type" content="{{ ogType | default: 'website' }}" />Common Eleventy OG mistakes
- Missing site URL in _data: without a base URL, image paths can't be made absolute. Always define
metadata.url. - page.url includes trailing slash: Eleventy's
page.urlhas a trailing slash by default. Account for this when concatenating URLs. - Not escaping values: use
| escapein Liquid or| escapein Nunjucks to prevent HTML injection in meta attributes.
Preview your OG tags free at OGFixer.com → Paste your Eleventy site URL to verify how your link card looks on Twitter, LinkedIn, Discord, and Slack.