Server Managed Meta Tags
Inertia Rails can manage a page's meta tags on the server instead of on the frontend. This means that link previews (such as on Facebook, LinkedIn, etc.) will include correct meta without server-side rendering.
Inertia Rails renders server defined meta tags into both the server rendered HTML and the client-side Inertia page props. Because the tags share unique head-key
attributes, the client will "take over" the meta tags after the initial page load.
Setup
Server Side
Simply add the inertia_meta_tags
helper to your layout. This will render the meta tags in the <head>
section of your HTML.
<!-- app/views/layouts/application.html.erb (or your custom layout) -->
<!DOCTYPE html>
<html>
<head>
...
<%= inertia_meta_tags %> <!-- Add this inside your <head> tag -->
</head>
</html>
NOTE
If you have a <title>
tag in your Rails layout, make sure it has the inertia
attribute on it so Inertia knows it should deduplicate it. The Inertia Rails install generator does this for you automatically.
Client Side
Copy the following code into your application. It should be rendered once in your application, such as in a layout component .
<script>
import { Head } from '@inertiajs/vue3'
import { usePage } from '@inertiajs/vue3'
import { h } from 'vue'
export default {
name: 'MetaTags',
setup() {
const page = usePage()
return () => {
const metaTags = page.props._inertia_meta || []
return h(Head, {}, () =>
metaTags.map((meta) => {
const { tagName, innerContent, headKey, httpEquiv, ...attrs } = meta
const attributes = {
key: headKey,
'head-key': headKey,
...attrs,
}
if (httpEquiv) {
attributes['http-equiv'] = httpEquiv
}
let content = null
if (innerContent != null) {
content =
typeof innerContent === 'string'
? innerContent
: JSON.stringify(innerContent)
}
return h(tagName, attributes, content)
}),
)
}
},
}
</script>
Rendering Meta Tags
Tags are defined as plain hashes and conform to the following structure:
# All fields are optional.
{
# Defaults to "meta" if not provided
tag_name: "meta",
# Used for <meta http-equiv="...">
http_equiv: "Content-Security-Policy",
# Used to deduplicate tags. InertiaRails will auto-generate one if not provided
head_key: "csp-header",
# Used with <script>, <title>, etc.
inner_content: "Some content",
# Any additional attributes will be passed directly to the tag.
# For example: name: "description", content: "Page description"
name: "description",
content: "A description of the page"
}
The <title>
tag has shortcut syntax:
{ title: "The page title" }
In the renderer
Add meta tags to an action by passing an array of hashes to the meta:
option in the render
method:
class EventsController < ApplicationController
def show
event = Event.find(params[:id])
render inertia: 'Event/Show', props: { event: event.as_json }, meta: [
{ title: "Check out the #{event.name} event!" },
{ name: 'description', content: event.description },
{ tag_name: 'script', type: 'application/ld+json', inner_content: { '@context': 'https://schema.org', '@type': 'Event', name: 'My Event' } }
]
end
end
Shared Meta Tags
Often, you will want to define default meta tags that are shared across certain pages and which you can override within a specific controller or action. Inertia Rails has an inertia_meta
controller instance method which references a store of meta tag data.
You can call it anywhere in a controller to manage common meta tags, such as in before_action
callbacks or directly in an action.
class EventsController < ApplicationController
before_action :set_meta_tags
def show
render inertia: 'Event/Show', props: { event: Event.find(params[:id]) }
end
private
def set_meta_tags
inertia_meta.add([
{ title: 'Look at this event!' }
])
end
end
The inertia_meta
API
The inertia_meta
method provides a simple API to manage your meta tags. You can add, remove, or clear tags as needed. The inertia_meta.remove
method accepts either a head_key
string or a block to filter tags.
# Add a single tag
inertia_meta.add({ title: 'Some Page title' })
# Add multiple tags at once
inertia_meta.add([
{ tag_name: 'meta', name: 'og:description', content: 'A description of the page' },
{ tag_name: 'meta', name: 'twitter:title', content: 'A title for Twitter' },
{ tag_name: 'title', inner_content: 'A title for the page', head_key: 'my_custom_head_key' },
{ tag_name: 'script', type: 'application/ld+json', inner_content: { '@context': 'https://schema.org', '@type': 'Event', name: 'My Event' } }
])
# Remove a specific tag by head_key
inertia_meta.remove("my_custom_head_key")
# Remove tags by a condition
inertia_meta.remove do |tag|
tag[:tag_name] == 'script' && tag[:type] == 'application/ld+json'
end
# Remove all tags
inertia_meta.clear
JSON-LD and Script Tags
Inertia Rails supports defining <script>
tags with type="application/ld+json"
for structured data. All other script tags will be marked as type="text/plain"
to prevent them from executing on the client side. Executable scripts should be added either in the Rails layout or using standard techniques in your frontend framework.
inertia_meta.add({
tag_name: "script",
type: "application/ld+json",
inner_content: {
"@context": "https://schema.org",
"@type": "Event",
name: "My Event",
startDate: "2023-10-01T10:00:00Z",
location: {
"@type": "Place",
name: "Event Venue",
address: "123 Main St, City, Country"
}
}
})
Deduplication
NOTE
The Svelte adapter does not have a <Head />
component. Inertia Rails will deduplicate meta tags on the server, and the Svelte component above will render them deduplicated accordingly.
Automatic Head Keys
Inertia Rails relies on the head-key
attribute and the <Head />
components that the Inertia.js core uses to manage meta tags and deduplicate them. Inertia.js core expects us to manage head-key
attributes and deduplication manually, but Inertia Rails will generate them automatically for you.
<meta>
tags will use thename
,property
, orhttp_equiv
attributes to generate a head key. This enables automatic deduplication of common meta tags likedescription
,og:title
, andtwitter:card
.- All other tags will deterministically generate a
head-key
based on the tag's attributes.
Allowing Duplicates
Sometimes, it is valid HTML to have multiple meta tags with the same name or property. If you want to allow duplicates, you can set the allow_duplicates
option to true
when defining the tag.
class StoriesController < ApplicationController
before_action do
inertia_meta.add({ name: 'article:author', content: 'Tony Gilroy' })
end
# Renders a single article:author meta tag
def single_author
render inertia: 'Stories/Show'
end
# Renders multiple article:author meta tags
def multiple_authors
render inertia: 'Stories/Show', meta: [
{ name: 'article:author', content: 'Dan Gilroy', allow_duplicates: true },
]
end
end
Manual Head Keys
Automatic head keys should cover the majority of use cases, but you can set head_key
manually if you need to control the deduplication behavior more precisely. For example, you may want to do this if you know you will remove a shared meta tag in a specific action.
# In a concern or `before_action` callback
inertia_meta.add([
{
tag_name: 'meta',
name: 'description',
content: 'A description of the page',
head_key: 'my_custom_head_key'
},
])
# Later in a specific action
inertia_meta.remove('my_custom_head_key')
Combining Meta Tag Methods
There are multiple ways to manage meta tags in Inertia Rails:
- Adding tags to a Rails layout such as
application.html.erb
. - Using the
<Head />
component from Inertia.js (or the Svelte head element) in the frontend. - Using the server driven meta tags feature described here.
Nothing prevents you from using these together, but for organizational purposes, we recommended using only one of the last two techniques.