PageStructuredData
PageStructuredData is a small Rails engine for rendering page-level SEO and social sharing metadata from one page object.
It helps Rails applications render:
- A
<title>tag - Basic
title,description, andimagemeta tags - Open Graph tags
- Twitter card tags
- Google-compatible JSON-LD structured data
- Breadcrumb structured data
- Article structured data for
BlogPostingandNewsArticle
Requirements
- Rails 7.0 or newer
- Slim 4.1 or newer
- A Ruby version supported by your Rails version
Installation
Add the gem to your application's Gemfile:
gem "page_structured_data"
Then install it:
bundle install
Configuration
Configure application-wide defaults in an initializer:
# config/initializers/page_structured_data.rb
Rails.application.config.after_initialize do
PageStructuredData.config do |config|
config.base_app_name = "AwesomestApp"
end
end
base_app_name is appended to generated page titles.
For example:
PageStructuredData.base_app_name = "AwesomestApp"
page = PageStructuredData::Page.new(
title: "Pricing",
extra_title: "Plans",
description: "Simple pricing for AwesomestApp"
)
page.page_title
# => "Pricing - Plans - AwesomestApp"
Rendering Meta Tags
Render the bundled partial from your application layout:
<%= render "page_structured_data/meta_tags",
page: @page_meta,
default_image_url: image_url("social/default.png") %>
default_image_url is optional. It is used when the page object does not provide an image.
This partial is only responsible for SEO, social sharing, and structured-data tags. Keep your normal Rails layout tags, such as CSRF, CSP, viewport, and favicon tags, in your application layout.
Basic Page Metadata
Set @page_meta in the controller or view before the layout renders:
@page_meta = PageStructuredData::Page.new(
title: "Home",
extra_title: "Official Page",
description: "Welcome to my page",
image: image_url("social/home.png")
)
The generated title is built from:
titleextra_title, when present- breadcrumb titles, when present
PageStructuredData.base_app_name, when present
The parts are joined with " - ".
Breadcrumbs
Create breadcrumbs with a hierarchy of page titles and URLs:
= PageStructuredData::Breadcrumbs.new(
hierarchy: [
{ title: "Resources", href: resources_url },
{ title: "Articles", href: resources_articles_url }
]
)
Pass the breadcrumbs into the page object:
@page_meta = PageStructuredData::Page.new(
title: "How to Structure Metadata",
description: "A guide to page metadata and structured data",
breadcrumb:
)
This renders BreadcrumbList JSON-LD similar to Google's breadcrumb structured data format.
Current compatibility note: when no breadcrumb object is passed, PageStructuredData::Page still creates an empty breadcrumb trail for the current page. This is existing behavior and should be considered part of the current public API.
Article Page Types
PageStructuredData includes page types for:
Use a page type when the current page represents an article:
article_page_type = PageStructuredData::PageTypes::BlogPosting.new(
headline: @article.title,
published_at: @article.published_at,
updated_at: @article.updated_at,
authors: [
{
name: @article..first.name,
url: @article..first.website
}
],
images: [
main_app.url_for(@article.cover_image.variant(:standard))
]
)
@page_meta = PageStructuredData::Page.new(
title: @article.title,
description: @article.summary,
image: main_app.url_for(@article.cover_image.variant(:standard)),
breadcrumb: ,
page_type: article_page_type
)
For news pages, use PageStructuredData::PageTypes::NewsArticle with the same arguments.
API Reference
PageStructuredData::Page
PageStructuredData::Page.new(
title:,
description: nil,
image: nil,
extra_title: "",
breadcrumb: nil,
page_type: nil
)
Important methods:
page_title: returns the composed page title.json_lds: returns the JSON-LD script tags for breadcrumbs and page type data.
PageStructuredData::Breadcrumbs
PageStructuredData::Breadcrumbs.new(
hierarchy: [
{ title: "Resources", href: "https://example.com/resources" }
]
)
Important methods:
titles: returns breadcrumb titles.json_ld(current_page_title:): returns aBreadcrumbListJSON-LD script tag.
Article Page Types
PageStructuredData::PageTypes::BlogPosting.new(
headline:,
published_at:,
updated_at:,
images: [],
authors: []
)
PageStructuredData::PageTypes::NewsArticle.new(
headline:,
published_at:,
updated_at:,
images: [],
authors: []
)
authors should be an array of hashes with :name and :url keys.
Development
Run the test suite:
bundle exec rake test
Verify the gem can be required:
ruby -Ilib -e 'require "page_structured_data"; puts PageStructuredData::VERSION'
Compatibility Policy
This gem is used in production applications. Changes should preserve existing public APIs and rendered output unless a breaking change is intentionally released in a major version.
Prefer additive APIs and tests that document current behavior before refactoring internals.
Contributing
Bug reports and pull requests are welcome on GitHub.
When contributing, please include tests for user-visible behavior and keep changes focused. For compatibility-sensitive behavior, describe the expected impact in the pull request.
License
The gem is available as open source under the terms of the MIT License.