Skip to content

Commit a908d97

Browse files
committed
Document SEO helpers
1 parent 1e32636 commit a908d97

File tree

3 files changed

+92
-1
lines changed

3 files changed

+92
-1
lines changed

app/helpers/better_together/application_helper.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ def host_community_logo_url
8080
rails_storage_proxy_url(attachment)
8181
end
8282

83+
# Returns the canonical URL for the current request, allowing overrides via
84+
# +content_for(:canonical_url)+.
85+
def canonical_url
86+
content_for?(:canonical_url) ? content_for(:canonical_url) : request.original_url
87+
end
88+
8389
# Builds SEO-friendly meta tags for the current view. Defaults are derived
8490
# from translations and fall back to the Open Graph description when set.
8591
# rubocop:todo Metrics/MethodLength
@@ -94,9 +100,17 @@ def seo_meta_tags # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
94100

95101
keywords = content_for?(:meta_keywords) ? content_for(:meta_keywords) : nil
96102

103+
canonical = canonical_url
104+
hreflang_tags = I18n.available_locales.map do |locale|
105+
tag.link(rel: 'alternate', hreflang: locale, href: url_for(locale:, only_path: false))
106+
end
107+
hreflang_tags << content_for(:hreflang_links) if content_for?(:hreflang_links)
108+
97109
tags = []
98110
tags << tag.meta(name: 'description', content: description)
99111
tags << tag.meta(name: 'keywords', content: keywords) if keywords.present?
112+
tags << tag.link(rel: 'canonical', href: canonical)
113+
tags.concat(hreflang_tags)
100114

101115
safe_join(tags, "\n")
102116
end
@@ -121,7 +135,7 @@ def open_graph_meta_tags # rubocop:todo Metrics/AbcSize, Metrics/MethodLength, M
121135
t('og.default_description', platform_name: host_platform.name)
122136
end
123137

124-
og_url = content_for?(:og_url) ? content_for(:og_url) : request.original_url
138+
og_url = content_for?(:og_url) ? content_for(:og_url) : canonical_url
125139

126140
og_image = content_for?(:og_image) ? content_for(:og_image) : host_community_logo_url
127141

docs/seo.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# SEO
2+
3+
The engine exposes helpers that output common search engine optimisation tags.
4+
5+
## Canonical URL
6+
7+
`seo_meta_tags` includes a canonical `<link>` tag pointing to the current request
8+
URL. You can override the URL by setting a `content_for` block:
9+
10+
```erb
11+
<% content_for :canonical_url, article_url(@article, locale: :en) %>
12+
```
13+
14+
## Hreflang links
15+
16+
Alternate language links are generated for each available locale. Additional
17+
links can be appended using `content_for :hreflang_links` and are merged with the
18+
default set:
19+
20+
```erb
21+
<% content_for :hreflang_links do %>
22+
<%= tag.link rel: 'alternate', hreflang: 'x-default', href: root_url %>
23+
<% end %>
24+
```
25+
26+
Links supplied via `content_for` are merged with the automatically generated
27+
links rather than replacing them.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# frozen_string_literal: true
2+
3+
require 'rails_helper'
4+
5+
module BetterTogether
6+
RSpec.describe ApplicationHelper, type: :helper do
7+
before do
8+
allow(helper).to receive(:host_platform).and_return(double(name: 'Test Platform', cache_key_with_version: 'test-platform'))
9+
allow(helper).to receive(:host_community_logo_url).and_return(nil)
10+
allow(controller.request).to receive(:original_url).and_return('http://test.host/en/current')
11+
allow(I18n).to receive(:available_locales).and_return(%i[en fr])
12+
allow(helper).to receive(:url_for) do |opts|
13+
"http://test.host/#{opts[:locale]}/current"
14+
end
15+
end
16+
17+
describe '#seo_meta_tags' do
18+
it 'includes default canonical and hreflang links' do
19+
html = helper.seo_meta_tags
20+
expect(html).to include('<link rel="canonical" href="http://test.host/en/current"')
21+
expect(html).to include('<link rel="alternate" hreflang="fr" href="http://test.host/fr/current"')
22+
end
23+
24+
it 'merges content_for overrides' do
25+
helper.content_for(:canonical_url, 'http://example.com/custom')
26+
helper.content_for(:hreflang_links, tag.link(rel: 'alternate', hreflang: 'es', href: 'http://test.host/es/current'))
27+
28+
html = helper.seo_meta_tags
29+
expect(html).to include('<link rel="canonical" href="http://example.com/custom"')
30+
expect(html).to include('<link rel="alternate" hreflang="fr" href="http://test.host/fr/current"')
31+
expect(html).to include('<link rel="alternate" hreflang="es" href="http://test.host/es/current"')
32+
end
33+
end
34+
35+
describe '#open_graph_meta_tags' do
36+
it 'defaults og:url to canonical_url' do
37+
allow(helper).to receive(:canonical_url).and_return('http://test.host/en/current')
38+
html = helper.open_graph_meta_tags
39+
expect(html).to include('<meta property="og:url" content="http://test.host/en/current"')
40+
end
41+
42+
it 'allows og_url override' do
43+
helper.content_for(:og_url, 'http://example.com/og')
44+
allow(helper).to receive(:canonical_url).and_return('http://test.host/en/current')
45+
html = helper.open_graph_meta_tags
46+
expect(html).to include('<meta property="og:url" content="http://example.com/og"')
47+
end
48+
end
49+
end
50+
end

0 commit comments

Comments
 (0)