Hello,
I was managing the SEO/schema.org on my different sites. Depending on the original theme or changes, I had to adapt my code for every small difference where is located the original information.
So I genericized my code. And I share it here in case it could help some of you.
PS : You better create a component shared amongst your projects.
PS 2 : This code is accepted on Google’s rich results
Basics
1 - Put all the files seo_**.html
below in your layouts/partials/
folder
2 - You only have to create a section [params.seo_json]
in your config.toml
to give the correspondance to where is located the information in your site/theme.
The variable names are given without site.Params.
For example:
[params.seo_json]
#here you will give the correspondance with your own information.
social_facebook = "global.facebook" # if your variable is in site.Params.global.facebook
image = "images" # if your variable is in site.Params.images
# etc. etc.
3 - Then, just call a partial in your <head>
section and that’s it, you’ll get a schema.org @type web on all your pages…
{{ partial "seo_metadata.html" . }}
4 - If you need more type (ex : @MyType) on a certain page, just add this to your Params (home) and/or frontmatter (Pages). And be sure to create a new seo_metadata_js_mytype.html
.
You can create more type based on this scheme.
# pour schema.org
typeseo = ["localbusiness", "mytype"]
Mandatory section in config.toml
[params.seo_json]
# basic used by website
social_facebook = "my real variable name"
social_twitter = "my real variable name"
social_instagram = "my real variable name"
image = "my real variable name"
defaultKeywords = "my real variable name"
# Used by localbusiness
logo = "my real variable name"
geo_type = "my real variable name"
geo_latitude = "my real variable name"
geo_longitude = "my real variable name"
officeAddress = "my real variable name"
officeAddressVille = "my real variable name"
officeAddressRegion = "my real variable name"
officeAddressCP = "my real variable name"
officeAddressPays = "my real variable name"
# phone MUST be unique for schema.org
officePhone = "my real variable name"
officeHorairesJours = "my real variable name"
officeHorairesOpen = "my real variable name"
officeHorairesClose = "my real variable name"
seo_metadata.html
<!-- Gestion du type @web sur toutes les pages -->
{{- $var := "seo_metadata_js_web.html" }}
{{ "<!-- schema.org : Web -->" | safeHTML }}
<script type="application/ld+json">
{{- partial $var . | safeJS -}}
</script>
<!-- Gestion du partial selon existence de ".typeseo" dans la page -->
{{- $context := . }}
{{- if .IsHome }}
<!-- HOME PAGE -->
{{- range site.Params.typeseo }}
{{- $var = (printf "seo_metadata_js_%s.html" . ) }}
{{- $infoschema := (printf "<!-- schema.org : %s -->" . ) }}
{{- $infoschema | safeHTML }}
<script type="application/ld+json">
{{- partial $var $context | safeJS -}}
</script>
{{- end }}
{{- else -}}
<!-- AUTRES PAGES -->
{{- range .Params.typeseo }}
{{- $var = (printf "seo_metadata_js_%s.html" . ) -}}
<script type="application/ld+json">
{{- partial $var $context | safeJS -}}
</script>
{{- end }}
{{- end }}
seo_metadata_title.html
{{- if .IsHome -}}
{{- site.Title | safeHTML -}}
{{- else -}}
{{- site.Title | safeHTML -}}{{- with .Title -}}{{ " | " }}{{- . | safeHTML -}}{{- end -}}
{{- end -}}
seo_metadata_description.html
{{- with .Description -}}
{{- . | safeHTML -}}
{{- else -}}
{{- with site.Params.Description -}}
{{- . | safeHTML -}}
{{- else -}}
{{- with site.Params.DefaultDescription -}}
{{- . | safeHTML -}}
{{- end -}}
{{- end -}}
{{- end -}}
seo_find_param.html
<!-- Manage SEO ld+json
Return the "real" param corresponding to the given variable -->
{{ $var := .var }}
{{ $temp := .context.Param ( printf "seo_json.%s" $var) }}
{{ $param_var := .context.Param $temp }}
{{ return $param_var }}
seo_metadata_js_web.html
<!-- Initialisation des variables selon [params.seo_json] de config.toml -->
<!-- $var = the desired variable for SEO ld+json -->
{{- $var := "social_facebook" | default "" -}}
{{- $seo_social_facebook := partial "seo_find_param.html" (dict "context" . "var" $var ) -}}
{{- $var := "social_twitter" | default "" -}}
{{- $seo_social_twitter := partial "seo_find_param.html" (dict "context" . "var" $var ) -}}
{{- $var := "social_instagram" | default "" -}}
{{- $seo_social_instagram := partial "seo_find_param.html" (dict "context" . "var" $var ) -}}
{{- $var := "image" | default "" -}}
{{- $seo_image := partial "seo_find_param.html" (dict "context" . "var" $var ) -}}
{{- $var := "defaultKeywords" | default "" -}}
{{- $seo_defaultKeywords := partial "seo_find_param.html" (dict "context" . "var" $var ) -}}
<!-- SEO code for ld-+son -->
{
"@context": "http://schema.org/",
"@type": "WebPage",
"mainEntityOfPage": {
"@type": "WebSite",
"@id": "{{ .Permalink }}",
"url": "{{ .Permalink }}",
"sameAs": [
{{- with $seo_social_facebook }}"{{ . }}",{{ end -}}
{{- with $seo_social_twitter }}"{{ . }}",{{ end -}}
{{- with $seo_social_instagram }}"{{ . }}"{{ end -}}
]
},
"@id": "{{ .Permalink }}",
"url": "{{ .Permalink }}",
"name" : "{{ partial "seo_metadata_title" . }}",
"headline" : "{{ partial "seo_metadata_title" . }}",
"description": "{{ partial "seo_metadata_description" . }}",
"image": "{{ range first 1 $seo_image }}{{ . | absURL }}{{ end }}",
"inLanguage" : "{{ .Language }}",
"copyrightYear" : "{{ now.Format "2006" }}",
"datePublished": "{{ now.Format "2006-01-02" }}",
{{ if not .Lastmod.IsZero }}"dateModified" : "{{ .Lastmod.Format "2006-01-02" }}",{{ end }}
{{ if .Keywords }}
"keywords" : "{{ delimit .Keywords ", " }}"
{{- else if $seo_defaultKeywords -}}
"keywords" : "{{ delimit $seo_defaultKeywords ", " }}"
{{ end -}}
}
seo_metadata_js_localbusiness.html
<!-- Initialisation des variables selon [params.seo_json] de config.toml -->
<!-- $var = the desired variable for SEO ld+json -->
{{- $var := "social_facebook" | default "" }}
{{- $seo_social_facebook := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "social_twitter" | default "" }}
{{- $seo_social_twitter := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "social_instagram" | default "" }}
{{- $seo_social_instagram := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "image" | default "" }}
{{- $seo_image := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "defaultKeywords" | default "" }}
{{- $seo_defaultKeywords := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "logo" | default "" }}
{{- $seo_logo := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "geo_type" | default "" }}
{{- $seo_geo_type := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "geo_latitude" | default "" }}
{{- $seo_geo_latitude := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "geo_longitude" | default "" }}
{{- $seo_geo_longitude := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeAddressName" | default "" }}
{{- $seo_officeAddressName := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeAddress" | default "" }}
{{- $seo_officeAddress := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeAddressCP" | default "" }}
{{- $seo_officeAddressCP := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeAddressVille" | default "" }}
{{- $seo_officeAddressVille := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeAddressPays" | default "" }}
{{- $seo_officeAddressPays := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeAddressRegion" | default "" }}
{{- $seo_officeAddressRegion := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officePhone" | default "" }}
{{- $seo_phone := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeHorairesJours" | default "" }}
{{- $seo_officeHorairesJours := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeHorairesOpen" | default "" }}
{{- $seo_officeHorairesOpen := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
{{- $var := "officeHorairesClose" | default "" }}
{{- $seo_officeHorairesClose := partial "seo_find_param.html" (dict "context" . "var" $var ) }}
<!-- SEO code for ld-+son -->
{
"@context": "http://schema.org/",
"@type": "WebPage",
"mainEntityOfPage": {
"@type": "WebSite",
"@id": "{{ .Permalink }}",
"url": "{{ .Permalink }}",
"sameAs": [
{{- with $seo_social_facebook }}"{{ . }}",{{ end -}}
{{- with $seo_social_twitter }}"{{ . }}",{{ end -}}
{{- with $seo_social_instagram }}"{{ . }}"{{ end -}}
]
},
"@id": "{{ .Permalink }}",
"url": "{{ .Permalink }}",
"name" : "{{ partial "seo_metadata_title" . }}",
"headline" : "{{ partial "seo_metadata_title" . }}",
"description": "{{ partial "seo_metadata_description" . }}",
"image": "{{ range first 1 $seo_image }}{{ . | absURL }}{{ end }}",
"inLanguage" : "{{ .Language }}",
"copyrightYear" : "{{ now.Format "2006" }}",
"datePublished": "{{ now.Format "2006-01-02" }}",
{{ if not .Lastmod.IsZero }}"dateModified" : "{{ .Lastmod.Format "2006-01-02" }}",{{ end }}
"mainEntity": {
"@type": "LocalBusiness",
"@id": "{{ .Permalink }}",
"url": "{{ .Permalink }}",
"name" : "{{ partial "seo_metadata_title" . }}",
"description": "{{ partial "seo_metadata_description" . }}",
"image": "{{ range first 1 $seo_image }}{{ . | absURL }}{{ end }}",
"photo": "{{ range first 1 $seo_image }}{{ . | absURL }}{{ end }}",
"logo": "{{ $seo_logo | absURL }}",
"address": {
"@type": "PostalAddress",
"streetAddress": "{{ $seo_officeAddress }}",
"addressLocality": "{{ $seo_officeAddressVille }}",
"addressRegion": "{{ $seo_officeAddressRegion }}",
"postalCode": "{{ $seo_officeAddressCP }}",
"addressCountry": "{{ $seo_officeAddressPays }}"
},
"telephone": "{{ $seo_phone | safeHTML }}",
"priceRange": "$",
"geo": {
"@type": "{{ $seo_geo_type }}",
"latitude": {{ $seo_geo_latitude }},
"longitude": {{ $seo_geo_longitude }}
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": [{{ range $i, $e := $seo_officeHorairesJours }}{{ if $i }}, {{ end }}"{{ $e }}"{{ end }}],
"opens": "{{ $seo_officeHorairesOpen }}",
"closes": "{{ $seo_officeHorairesClose }}"
}
]
},
{{ if .Keywords }}
"keywords" : "{{ delimit .Keywords ", " }}"
{{- else if $seo_defaultKeywords -}}
"keywords" : "{{ delimit $seo_defaultKeywords ", " }}"
{{ end -}}
}