Manage easily any SEO schema.org thru your different sites

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 -}}
}

10 Likes