jekyll-soopr-seo-tag 2.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/actions/memprof.rb +14 -0
- data/.github/workflows/third-party.yml +61 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +19 -0
- data/.rubocop_todo.yml +13 -0
- data/.travis.yml +18 -0
- data/Gemfile +8 -0
- data/History.markdown +202 -0
- data/LICENSE.txt +21 -0
- data/docs/README.md +34 -0
- data/docs/_config.yml +10 -0
- data/docs/_layouts/default.html +18 -0
- data/docs/advanced-usage.md +156 -0
- data/docs/installation.md +24 -0
- data/docs/usage.md +80 -0
- data/jekyll-soopr-seo-tag.gemspec +34 -0
- data/lib/jekyll-seo-tag/author_drop.rb +93 -0
- data/lib/jekyll-seo-tag/drop.rb +252 -0
- data/lib/jekyll-seo-tag/filters.rb +14 -0
- data/lib/jekyll-seo-tag/image_drop.rb +78 -0
- data/lib/jekyll-seo-tag/json_ld.rb +31 -0
- data/lib/jekyll-seo-tag/json_ld_drop.rb +95 -0
- data/lib/jekyll-seo-tag/soopr_drop.rb +54 -0
- data/lib/jekyll-seo-tag/url_helper.rb +23 -0
- data/lib/jekyll-seo-tag/version.rb +10 -0
- data/lib/jekyll-soopr-seo-tag.rb +96 -0
- data/lib/template.html +125 -0
- data/script/bootstrap +5 -0
- data/script/cibuild +7 -0
- data/script/release +38 -0
- data/script/site +3 -0
- metadata +153 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class SeoTag
|
5
|
+
# A drop representing the page image
|
6
|
+
# The image path will be pulled from:
|
7
|
+
#
|
8
|
+
# 1. The `image` key if it's a string
|
9
|
+
# 2. The `image.path` key if it's a hash
|
10
|
+
# 3. The `image.facebook` key
|
11
|
+
# 4. The `image.twitter` key
|
12
|
+
class ImageDrop < Jekyll::Drops::Drop
|
13
|
+
include Jekyll::SeoTag::UrlHelper
|
14
|
+
|
15
|
+
# Initialize a new ImageDrop
|
16
|
+
#
|
17
|
+
# page - The page hash (e.g., Page#to_liquid)
|
18
|
+
# context - the Liquid::Context
|
19
|
+
def initialize(page: nil, context: nil)
|
20
|
+
raise ArgumentError unless page && context
|
21
|
+
|
22
|
+
@mutations = {}
|
23
|
+
@page = page
|
24
|
+
@context = context
|
25
|
+
end
|
26
|
+
|
27
|
+
# Called path for backwards compatability, this is really
|
28
|
+
# the escaped, absolute URL representing the page's image
|
29
|
+
# Returns nil if no image path can be determined
|
30
|
+
def path
|
31
|
+
@path ||= filters.uri_escape(absolute_url) if absolute_url
|
32
|
+
end
|
33
|
+
alias_method :to_s, :path
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_accessor :page
|
38
|
+
attr_accessor :context
|
39
|
+
|
40
|
+
# The normalized image hash with a `path` key (which may be nil)
|
41
|
+
def image_hash
|
42
|
+
@image_hash ||= begin
|
43
|
+
image_meta = page["image"]
|
44
|
+
|
45
|
+
if image_meta.is_a?(Hash)
|
46
|
+
{ "path" => nil }.merge!(image_meta)
|
47
|
+
elsif image_meta.is_a?(String)
|
48
|
+
{ "path" => image_meta }
|
49
|
+
else
|
50
|
+
{ "path" => nil }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
alias_method :fallback_data, :image_hash
|
55
|
+
|
56
|
+
def raw_path
|
57
|
+
@raw_path ||= begin
|
58
|
+
image_hash["path"] || image_hash["facebook"] || image_hash["twitter"]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def absolute_url
|
63
|
+
return unless raw_path
|
64
|
+
return @absolute_url if defined? @absolute_url
|
65
|
+
|
66
|
+
@absolute_url = if raw_path.is_a?(String) && absolute_url?(raw_path) == false
|
67
|
+
filters.absolute_url raw_path
|
68
|
+
else
|
69
|
+
raw_path
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def filters
|
74
|
+
@filters ||= Jekyll::SeoTag::Filters.new(context)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class SeoTag
|
5
|
+
# This module is deprecated, but is included in the Gem to avoid a breaking
|
6
|
+
# change and should be removed at the next major version bump
|
7
|
+
module JSONLD
|
8
|
+
METHODS_KEYS = {
|
9
|
+
:json_context => "@context",
|
10
|
+
:type => "@type",
|
11
|
+
:name => "name",
|
12
|
+
:page_title => "headline",
|
13
|
+
:json_author => "author",
|
14
|
+
:json_image => "image",
|
15
|
+
:date_published => "datePublished",
|
16
|
+
:date_modified => "dateModified",
|
17
|
+
:description => "description",
|
18
|
+
:publisher => "publisher",
|
19
|
+
:main_entity => "mainEntityOfPage",
|
20
|
+
:links => "sameAs",
|
21
|
+
:canonical_url => "url",
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
# Self should be a Jekyll::SeoTag::Drop instance (when extending the module)
|
25
|
+
def json_ld
|
26
|
+
Jekyll.logger.warn "Jekyll::SeoTag::JSONLD is deprecated"
|
27
|
+
@json_ld ||= JSONLDDrop.new(self)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class SeoTag
|
5
|
+
class JSONLDDrop < Jekyll::Drops::Drop
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegator :page_drop, :name, :name
|
9
|
+
def_delegator :page_drop, :description, :description
|
10
|
+
def_delegator :page_drop, :canonical_url, :url
|
11
|
+
def_delegator :page_drop, :page_title, :headline
|
12
|
+
def_delegator :page_drop, :date_modified, :dateModified
|
13
|
+
def_delegator :page_drop, :date_published, :datePublished
|
14
|
+
def_delegator :page_drop, :links, :sameAs
|
15
|
+
def_delegator :page_drop, :logo, :logo
|
16
|
+
def_delegator :page_drop, :type, :type
|
17
|
+
|
18
|
+
# Expose #type and #logo as private methods and #@type as a public method
|
19
|
+
alias_method :"@type", :type
|
20
|
+
private :type
|
21
|
+
private :logo
|
22
|
+
|
23
|
+
VALID_ENTITY_TYPES = %w(BlogPosting CreativeWork).freeze
|
24
|
+
VALID_AUTHOR_TYPES = %w(Organization Person).freeze
|
25
|
+
private_constant :VALID_ENTITY_TYPES, :VALID_AUTHOR_TYPES
|
26
|
+
|
27
|
+
# page_drop should be an instance of Jekyll::SeoTag::Drop
|
28
|
+
def initialize(page_drop)
|
29
|
+
@mutations = {}
|
30
|
+
@page_drop = page_drop
|
31
|
+
end
|
32
|
+
|
33
|
+
def fallback_data
|
34
|
+
@fallback_data ||= {
|
35
|
+
"@context" => "https://schema.org",
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def author
|
40
|
+
return unless page_drop.author["name"]
|
41
|
+
|
42
|
+
author_type = page_drop.author["type"]
|
43
|
+
return if author_type && !VALID_AUTHOR_TYPES.include?(author_type)
|
44
|
+
|
45
|
+
{
|
46
|
+
"@type" => author_type || "Person",
|
47
|
+
"name" => page_drop.author["name"],
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def image
|
52
|
+
return unless page_drop.image
|
53
|
+
return page_drop.image.path if page_drop.image.keys.length == 1
|
54
|
+
|
55
|
+
hash = page_drop.image.to_h
|
56
|
+
hash["url"] = hash.delete("path")
|
57
|
+
hash["@type"] = "imageObject"
|
58
|
+
hash
|
59
|
+
end
|
60
|
+
|
61
|
+
def publisher
|
62
|
+
return unless logo
|
63
|
+
|
64
|
+
output = {
|
65
|
+
"@type" => "Organization",
|
66
|
+
"logo" => {
|
67
|
+
"@type" => "ImageObject",
|
68
|
+
"url" => logo,
|
69
|
+
},
|
70
|
+
}
|
71
|
+
output["name"] = page_drop.author.name if page_drop.author.name
|
72
|
+
output
|
73
|
+
end
|
74
|
+
|
75
|
+
def main_entity
|
76
|
+
return unless VALID_ENTITY_TYPES.include?(type)
|
77
|
+
|
78
|
+
{
|
79
|
+
"@type" => "WebPage",
|
80
|
+
"@id" => page_drop.canonical_url,
|
81
|
+
}
|
82
|
+
end
|
83
|
+
alias_method :mainEntityOfPage, :main_entity
|
84
|
+
private :main_entity
|
85
|
+
|
86
|
+
def to_json
|
87
|
+
to_h.reject { |_k, v| v.nil? }.to_json
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
attr_reader :page_drop
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class SeoTag
|
5
|
+
# A drop representing soopr and soopr's publish token
|
6
|
+
# The publish key will be pulled from:
|
7
|
+
#
|
8
|
+
# 1. The `soopr` key if it's a string
|
9
|
+
# 2. The `soopr.publish_token` if it's a hash
|
10
|
+
# 3. The `soopr.publish_key` if it's a hash
|
11
|
+
class SooprDrop < Jekyll::Drops::Drop
|
12
|
+
|
13
|
+
# Initialize a new SooprDrop
|
14
|
+
#
|
15
|
+
# page - The page hash (e.g., Page#to_liquid)
|
16
|
+
# context - the Liquid::Context
|
17
|
+
def initialize(page: nil, site: nil)
|
18
|
+
raise ArgumentError unless page && site
|
19
|
+
|
20
|
+
@mutations = {}
|
21
|
+
@page = page
|
22
|
+
@site = site
|
23
|
+
end
|
24
|
+
|
25
|
+
def publish_token
|
26
|
+
soopr_hash["publish_token"] || soopr_hash["publish_key"]
|
27
|
+
end
|
28
|
+
alias_method :to_s, :publish_token
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :page
|
33
|
+
attr_reader :site
|
34
|
+
|
35
|
+
|
36
|
+
def soopr_hash
|
37
|
+
@soopr_hash ||= begin
|
38
|
+
return {} unless site["soopr"].is_a?(Hash)
|
39
|
+
|
40
|
+
soopr_hash = site["soopr"]
|
41
|
+
soopr_hash.is_a?(Hash) ? soopr_hash : {}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Since author_hash is aliased to fallback_data, any values in the hash
|
46
|
+
# will be exposed via the drop, allowing support for arbitrary metadata
|
47
|
+
alias_method :fallback_data, :soopr_hash
|
48
|
+
end
|
49
|
+
|
50
|
+
def filters
|
51
|
+
@filters ||= Jekyll::SeoTag::Filters.new(context)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
class SeoTag
|
5
|
+
# Mixin to share common URL-related methods between class
|
6
|
+
module UrlHelper
|
7
|
+
private
|
8
|
+
|
9
|
+
# Determines if the given string is an absolute URL
|
10
|
+
#
|
11
|
+
# Returns true if an absolute URL.
|
12
|
+
# Retruns false if it's a relative URL
|
13
|
+
# Returns nil if it is not a string or can't be parsed as a URL
|
14
|
+
def absolute_url?(string)
|
15
|
+
return unless string
|
16
|
+
|
17
|
+
Addressable::URI.parse(string).absolute?
|
18
|
+
rescue Addressable::URI::InvalidURIError
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "jekyll"
|
4
|
+
require "jekyll-seo-tag/version"
|
5
|
+
|
6
|
+
module Jekyll
|
7
|
+
class SeoTag < Liquid::Tag
|
8
|
+
autoload :JSONLD, "jekyll-seo-tag/json_ld"
|
9
|
+
autoload :AuthorDrop, "jekyll-seo-tag/author_drop"
|
10
|
+
autoload :ImageDrop, "jekyll-seo-tag/image_drop"
|
11
|
+
autoload :JSONLDDrop, "jekyll-seo-tag/json_ld_drop"
|
12
|
+
autoload :UrlHelper, "jekyll-seo-tag/url_helper"
|
13
|
+
autoload :Drop, "jekyll-seo-tag/drop"
|
14
|
+
autoload :Filters, "jekyll-seo-tag/filters"
|
15
|
+
autoload :SooprDrop, "jekyll-seo-tag/soopr_drop"
|
16
|
+
|
17
|
+
|
18
|
+
attr_accessor :context
|
19
|
+
|
20
|
+
# Matches all whitespace that follows either
|
21
|
+
# 1. A '}', which closes a Liquid tag
|
22
|
+
# 2. A '{', which opens a JSON block
|
23
|
+
# 3. A '>' followed by a newline, which closes an XML tag or
|
24
|
+
# 4. A ',' followed by a newline, which ends a JSON line
|
25
|
+
# We will strip all of this whitespace to minify the template
|
26
|
+
# We will not strip any whitespace if the next character is a '-'
|
27
|
+
# so that we do not interfere with the HTML comment at the
|
28
|
+
# very begining
|
29
|
+
MINIFY_REGEX = %r!(?<=[{}]|[>,]\n)\s+(?\!-)!.freeze
|
30
|
+
|
31
|
+
def initialize(_tag_name, text, _tokens)
|
32
|
+
super
|
33
|
+
@text = text
|
34
|
+
end
|
35
|
+
|
36
|
+
def render(context)
|
37
|
+
@context = context
|
38
|
+
SeoTag.template.render!(payload, info)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def options
|
44
|
+
{
|
45
|
+
"version" => Jekyll::SeoTag::VERSION,
|
46
|
+
"title" => title?,
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def payload
|
51
|
+
# site_payload is an instance of UnifiedPayloadDrop. See https://git.io/v5ajm
|
52
|
+
context.registers[:site].site_payload.tap do |site_payload|
|
53
|
+
site_payload["page"] = context.registers[:page]
|
54
|
+
site_payload["paginator"] = context["paginator"]
|
55
|
+
site_payload["seo_tag"] = drop
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def drop
|
60
|
+
if context.registers[:site].liquid_renderer.respond_to?(:cache)
|
61
|
+
Jekyll::SeoTag::Drop.new(@text, @context)
|
62
|
+
else
|
63
|
+
@drop ||= Jekyll::SeoTag::Drop.new(@text, @context)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def info
|
68
|
+
{
|
69
|
+
:registers => context.registers,
|
70
|
+
:filters => [Jekyll::Filters],
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
class << self
|
75
|
+
def template
|
76
|
+
@template ||= Liquid::Template.parse template_contents
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def template_contents
|
82
|
+
@template_contents ||= begin
|
83
|
+
File.read(template_path).gsub(MINIFY_REGEX, "")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def template_path
|
88
|
+
@template_path ||= begin
|
89
|
+
File.expand_path "./template.html", File.dirname(__FILE__)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Liquid::Template.register_tag("seo", Jekyll::SeoTag)
|
data/lib/template.html
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
<!-- Begin Jekyll SEO tag v{{ seo_tag.version }} -->
|
2
|
+
{% if seo_tag.title? %}
|
3
|
+
<title>{{ seo_tag.title }}</title>
|
4
|
+
{% endif %}
|
5
|
+
|
6
|
+
<meta name="generator" content="Jekyll v{{ jekyll.version }}" />
|
7
|
+
|
8
|
+
{% if seo_tag.page_title %}
|
9
|
+
<meta property="og:title" content="{{ seo_tag.page_title }}" />
|
10
|
+
{% endif %}
|
11
|
+
|
12
|
+
{% if seo_tag.author.name %}
|
13
|
+
<meta name="author" content="{{ seo_tag.author.name }}" />
|
14
|
+
{% endif %}
|
15
|
+
|
16
|
+
<meta property="og:locale" content="{{ seo_tag.page_locale }}" />
|
17
|
+
|
18
|
+
{% if seo_tag.description %}
|
19
|
+
<meta name="description" content="{{ seo_tag.description }}" />
|
20
|
+
<meta property="og:description" content="{{ seo_tag.description }}" />
|
21
|
+
{% endif %}
|
22
|
+
|
23
|
+
{% if site.url %}
|
24
|
+
<link rel="canonical" href="{{ seo_tag.canonical_url }}" />
|
25
|
+
<meta property="og:url" content="{{ seo_tag.canonical_url }}" />
|
26
|
+
{% endif %}
|
27
|
+
|
28
|
+
{% if seo_tag.site_title %}
|
29
|
+
<meta property="og:site_name" content="{{ seo_tag.site_title }}" />
|
30
|
+
{% endif %}
|
31
|
+
|
32
|
+
{% if seo_tag.image && seo_tag.image.path %}
|
33
|
+
<meta property="og:image" content="{{ seo_tag.image.path }}" />
|
34
|
+
{% if seo_tag.image.height %}
|
35
|
+
<meta property="og:image:height" content="{{ seo_tag.image.height }}" />
|
36
|
+
{% endif %}
|
37
|
+
{% if seo_tag.image.width %}
|
38
|
+
<meta property="og:image:width" content="{{ seo_tag.image.width }}" />
|
39
|
+
{% endif %}
|
40
|
+
{% elsif seo_tag.soopr %}
|
41
|
+
<meta property="og:image" content="https://soopr.xyz/images/card?url={{ seo_tag.canonical_url }}" />
|
42
|
+
{% endif %}
|
43
|
+
|
44
|
+
{% if page.date %}
|
45
|
+
<meta property="og:type" content="article" />
|
46
|
+
<meta property="article:published_time" content="{{ page.date | date_to_xmlschema }}" />
|
47
|
+
{% endif %}
|
48
|
+
|
49
|
+
{% if paginator.previous_page %}
|
50
|
+
<link rel="prev" href="{{ paginator.previous_page_path | absolute_url }}" />
|
51
|
+
{% endif %}
|
52
|
+
{% if paginator.next_page %}
|
53
|
+
<link rel="next" href="{{ paginator.next_page_path | absolute_url }}" />
|
54
|
+
{% endif %}
|
55
|
+
|
56
|
+
|
57
|
+
{% if seo_tag.image %}
|
58
|
+
<meta name="twitter:card" content="{{ page.twitter.card | default: site.twitter.card | default: "summary_large_image" }}" />
|
59
|
+
<meta property="twitter:image" content="{{ seo_tag.image.path }}" />
|
60
|
+
{% elsif seo_tag.soopr %}
|
61
|
+
<meta name="twitter:card" content="summary_large_image" />
|
62
|
+
<meta property="og:image" content="https://soopr.xyz/images/card?url={{ seo_tag.canonical_url }}" />
|
63
|
+
{% else %}
|
64
|
+
<meta name="twitter:card" content="summary" />
|
65
|
+
{% endif %}
|
66
|
+
|
67
|
+
{% if seo_tag.page_title %}
|
68
|
+
<meta property="twitter:title" content="{{ seo_tag.page_title }}" />
|
69
|
+
{% endif %}
|
70
|
+
|
71
|
+
{% if site.twitter %}
|
72
|
+
<meta name="twitter:site" content="@{{ site.twitter.username | remove:'@' }}" />
|
73
|
+
|
74
|
+
{% if seo_tag.author.twitter %}
|
75
|
+
<meta name="twitter:creator" content="@{{ seo_tag.author.twitter | remove:'@' }}" />
|
76
|
+
{% endif %}
|
77
|
+
{% endif %}
|
78
|
+
|
79
|
+
{% if site.facebook %}
|
80
|
+
{% if site.facebook.admins %}
|
81
|
+
<meta property="fb:admins" content="{{ site.facebook.admins }}" />
|
82
|
+
{% endif %}
|
83
|
+
|
84
|
+
{% if site.facebook.publisher %}
|
85
|
+
<meta property="article:publisher" content="{{ site.facebook.publisher }}" />
|
86
|
+
{% endif %}
|
87
|
+
|
88
|
+
{% if site.facebook.app_id %}
|
89
|
+
<meta property="fb:app_id" content="{{ site.facebook.app_id }}" />
|
90
|
+
{% endif %}
|
91
|
+
{% endif %}
|
92
|
+
|
93
|
+
{% if site.webmaster_verifications %}
|
94
|
+
{% if site.webmaster_verifications.google %}
|
95
|
+
<meta name="google-site-verification" content="{{ site.webmaster_verifications.google }}" />
|
96
|
+
{% endif %}
|
97
|
+
|
98
|
+
{% if site.webmaster_verifications.bing %}
|
99
|
+
<meta name="msvalidate.01" content="{{ site.webmaster_verifications.bing }}" />
|
100
|
+
{% endif %}
|
101
|
+
|
102
|
+
{% if site.webmaster_verifications.alexa %}
|
103
|
+
<meta name="alexaVerifyID" content="{{ site.webmaster_verifications.alexa }}" />
|
104
|
+
{% endif %}
|
105
|
+
|
106
|
+
{% if site.webmaster_verifications.yandex %}
|
107
|
+
<meta name="yandex-verification" content="{{ site.webmaster_verifications.yandex }}" />
|
108
|
+
{% endif %}
|
109
|
+
|
110
|
+
{% if site.webmaster_verifications.baidu %}
|
111
|
+
<meta name="baidu-site-verification" content="{{ site.webmaster_verifications.baidu }}" />
|
112
|
+
{% endif %}
|
113
|
+
{% elsif site.google_site_verification %}
|
114
|
+
<meta name="google-site-verification" content="{{ site.google_site_verification }}" />
|
115
|
+
{% endif %}
|
116
|
+
|
117
|
+
<script type="application/ld+json">
|
118
|
+
{{ seo_tag.json_ld | jsonify }}
|
119
|
+
</script>
|
120
|
+
|
121
|
+
{% if seo_tag.soopr %}
|
122
|
+
<script async defer data-soopr-token="{{seo_tag.soopr.publish_token}}" src="https://sdk.soopr.co/soopr.js" ></script>
|
123
|
+
{% endif %}
|
124
|
+
|
125
|
+
<!-- End Jekyll SEO tag -->
|