How to add Job Vacancy to Google from a static Hugo website

Contents

Are you advertising for job positions on your website?

Trying to hire somebody is a bit difficult these days in some industries, especially when companies looking carefully at their budgets, everything is getting more expensive so is salary expectations higher than usual.

When the good places to advertise a job vacancy are plenty around if the company decided to put it on the website, it’s worth using the power of Google and getting this offer working for the company (it will not find itself without the right approach).

If you looked through Google for job offers you may see that some offers are displayed directly in search results (Jobs section) and they are not paid advertising (at least not most of them). Most of them are pulled from other sites.

The good thing is, that you can add your job vacancy to Google for free as well, you just need to inform the search engine the right way.

The right way to do that is with JobPosting Schema.

The way I did it on one of my websites is by using structured data (Schema) formatted in JSON, Hugo shortcodes or using partials.

Thanks to the shortcodes you are setting JSON Schema once, and then reusing it through your markdown with shortcodes parameters.

There are other formats for implementing Schema into the website which include Microdata. I prefer JSON type schema (Google also), as this is working strictly in the background and don’t require adjusting your website design to it. When implemented, nothing changes for the user. The website is looking and acting the same, just Google and other search engines see the changes implemented and are using them accordingly.

The shortcodes solution is good if you advertising one or more job vacancies on a single page on your website (like /vacancies/)

If you split each position into multiple pages (like /vacancies/sales-person/, /vacancies/cleaner/), there is a better option for that with the use of Hugo partials which I will cover as well.

But firstly, let’s deal with the Schema and the requirements to get our job vacancies into Google.

JobPosting Schema #

Firstly we will follow the Google requirements for adding structured data to job postings.

Before you start, make sure that your website is added to Google Search Console, so you can get pages indexed quicker, and see if they are discovered and displayed in Google in the first place.

The covid pandemic has changed the way how people are hired and this introduced a new type of work environment – work from home. Before it wasn’t something present very often, but right now it become the new norm. Sometimes this “flexibility” brining more productivity to the business if the “technology” and “new work-home environment” are working towards that.

Google adjusted itself creating a part of Standard job posting schema also Work from home job posting.

Let’s start with the first option on which I will concentrate the most.

Standard job posting #

<script type="application/ld+json">
  {
    "@context" : "https://schema.org/",
    "@type" : "JobPosting",
    "title" : "Sales Person",
    "description" : "<p>We are looking for experienced sales person who can do more.</p>",
    "identifier": {
      "@type": "PropertyValue",
      "name": "Company Limited",
      "value": "ABC123"
    },
    "datePosted" : "2022-05-10",
    "validThrough" : "2022-12-23T00:00",
    "employmentType" : "FULL_TIME",
    "hiringOrganization" : {
      "@type" : "Organization",
      "name" : "Company Limited",
      "sameAs" : "https://www.example.com",
      "logo" : "https://www.example.com/images/logo.svg"
    },
    "jobLocation": {
    "@type": "Place",
      "address": {
      "@type": "PostalAddress",
      "streetAddress": "123 Street Road",
      "addressLocality": "Leeds",
      "addressRegion": "West Yorkshire",
      "postalCode": "LS99 0XN",
      "addressCountry": "UK"
      }
    },
    "baseSalary": {
      "@type": "MonetaryAmount",
      "currency": "GBP",
      "value": {
        "@type": "QuantitativeValue",
        "value": 11.50,
        "unitText": "HOUR"
      }
    }
  }
</script>

Google described in Structured data type definitions what is the meaning of each parameter and what content is acceptable.

Work from home job posting #

<script type="application/ld+json">
  {
    "@context" : "https://schema.org/",
    "@type" : "JobPosting",
    "title" : "Sales Person",
    "description" : "<p>We are looking for experienced sales person who can do more.</p>",
    "identifier": {
      "@type": "PropertyValue",
      "name": "Company Limited",
      "value": "ABC123"
    },
    "datePosted" : "2022-05-10",
      "validThrough" : "2022-12-23T00:00",
      "applicantLocationRequirements": {
        "@type": "Country",
        "name": "UK"
      },
      "jobLocationType": "TELECOMMUTE",
      "employmentType": "FULL_TIME",
      "hiringOrganization" : {
        "@type" : "Organization",
        "name" : "Company Limited",
        "sameAs" : "https://www.example.com",
        "logo" : "https://www.example.com/images/logo.svg"
      },
      "baseSalary": {
        "@type": "MonetaryAmount",
        "currency": "GBP",
        "value": {
          "@type": "QuantitativeValue",
          "value": 11.50,
          "unitText": "HOUR"
        }
      }
    }
</script>

Building JobPosting Schema shortcodes #

Let’s create a shortcode called vacancy by creating the file vacancy.html in the folder /layouts/shortcodes/.

This file will contain one of the above JobPosting Schema with some modifications. Before we start with modifications, let’s understand how we will use this in our markdown file.

Hugo shortcodes can be called on their own

{{% vacancy %}}

or with specified parameter/s like

{{% vacancy "parameter1" "parameter2" "parameter3" %}}

Where parameter1 we can later call inside using {{ .Get 0 }}, parameter2 using {{ .Get 1 }} etc.

If our company is always the same, we can pre-fill this information in our schema as we will not need to fill them each time. Same we can do with address details and the currency. In that case, we will limit the number of parameters in our shortcode.

Here is an example of The Example Company

<script type="application/ld+json">
  {
    "@context" : "https://schema.org/",
    "@type" : "JobPosting",
    "title" : "{{ .Get 0 }}",
    "description" : "{{ .Get 1 }}",
    "identifier": {
      "@type": "PropertyValue",
      "name": "Example Company Limited",
      "value": "{{ .Get 2 }}"
    },
    "datePosted" : "{{ .Get 3 }}",
    "validThrough" : "{{ .Get 4 }}T00:00",
    "employmentType" : "{{ .Get 5 }}",
    "hiringOrganization" : {
      "@type" : "Organization",
      "name" : "Example Company Limited",
      "sameAs" : "https://www.example.com",
      "logo" : "https://www.example.com/images/logo.svg"
    },
    "jobLocation": {
    "@type": "Place",
      "address": {
      "@type": "PostalAddress",
      "streetAddress": "123 Street Road",
      "addressLocality": "Leeds",
      "addressRegion": "West Yorkshire",
      "postalCode": "LS99 0XN",
      "addressCountry": "UK"
      }
    },
    "baseSalary": {
      "@type": "MonetaryAmount",
      "currency": "GBP",
      "value": {
        "@type": "QuantitativeValue",
        "value": {{ .Get 6 }},
        "unitText": "{{ .Get 7 }}"
      }
    }
  }
</script>

In this example, the shortcode will require 8 parameters to be specified each time to work correctly.

{{% vacancy "0" "1" "2" "3" "4" "5" "6" "7" %}}

Where

  • "0" will contain Job Title;
  • "1" will contain job description in HTML format;
  • "2" will contain unique Job value, number or string;
  • "3" will contain date when job become available;
  • "4" will contain date till when job shall be displayed in Google;
  • "5" will contain employment type, like FULL_TIME;
  • "6" will contain rate, like 10.50
  • "7" will contain unit type of the parameter "7", like per HOUR.

Here is an example:

{{% google-jobs-schema "Sales Person" "<p>An exciting position has become available for a full-time Sales Person. The successful candidate will work 40 hours per week with the possibility of extra hours during busy periods and holidays.</p>" "SP012022" "2022-05-10" "2022-12-23" "FULL_TIME" "10.50" "HOUR" %}}

This method may not be the easiest to use, as every time you will need to fill all parameters, as in another case the shortcode will return an error. However, this gives you the flexibility to put this on whatever page you will need, as well you will be able to put this multiple times on a single page.

If you create a separate page on your website that will be designed for one job position, the other solution with archetypes and partials may be easier to use. This will also allow you nicely to integrate the job vacancy section into your website layout.

Using Archetypes and Partials for JobPosting Schema #

Let’s start by creating our schema.html partial in the partials folder (or in layouts or our theme).

We will be calling our file in between <head> section:

{{ partial "schema.html" . }}

Because you may have other schema incorporated into your website, so the file schema.html may already exist, we will need to use JobPosting Schema only when is requested (on the page that is only related to job vacancy).

Let’s start with the following

{{ if .Params.jobPosting }}
<script type="application/ld+json">
  {
    "@context" : "https://schema.org/",
    "@type" : "JobPosting",
    "title" : "{{ .Params.jobTitle }}",
    "description" : "{{ .Params.jobDescription }}",
    "identifier": {
      "@type": "PropertyValue",
      "name": "Example Company Limited",
      "value": "{{ .Params.jobID }}"
    },
    "datePosted" : "{{ .Params.datePosted }}",
    "validThrough" : "{{ .Params.validThrough }}T00:00",
    "employmentType" : [ {{ .Params.employmentType }} ],
    "hiringOrganization" : {
      "@type" : "Organization",
      "name" : "Example Company Limited",
      "sameAs" : "https://www.example.com",
      "logo" : "https://www.example.com/images/logo.svg"
    },
    "jobLocation": {
    "@type": "Place",
      "address": {
      "@type": "PostalAddress",
      "streetAddress": "123 Street Road",
      "addressLocality": "Leeds",
      "addressRegion": "West Yorkshire",
      "postalCode": "LS99 0XN",
      "addressCountry": "UK"
      }
    },
    "baseSalary": {
      "@type": "MonetaryAmount",
      "currency": "GBP",
      "value": {
        "@type": "QuantitativeValue",
        "value": {{ .Params.jobRate }},
        "unitText": "{{ .Params.jobRateUnit }}"
      }
    }
  }
</script>
{{ end }}

This will be called only for a page, where the markdown file contains the jobPosting parameter set for true.

Let’s start by creating our vacancies archetype in the /archetypes/ folder and fill it with some basic information:

---
title: "{{ replace .Name "-" " " | title }}"
url: '/.../'
description: ''

jobPosting: true
jobTitle: "Job Title"
jobDescription: "Put your job description here in HTML format"
jobID: JOBID001
datePosted: 2022-05-10
validThrough: 2022-12-23
employmentType: 
 - FULL_TIME
 - TEMPORARY
jobRate: 10.50
jobRateUnit: HOUR

---

Put the content of your markdown file

As you will see, the parameters in the archetypes file match with parameters that are later filled in the schema file.

Using the following command we will be able to use this template to create job vacancies, for example:

hugo new vacancies/sales-person.md

The parameter jobPosting will invoke the relevant part from our schema.html file on the page with job advertise.

Removing JobPosting from Google #

As mentioned on the Google page in the Remove a job posting section, we can do this using the following:

Ensure the validThrough property is populated and in the past.

In that case, we just need to change the date to which the job is valid.

Remove the page entirely (so that requesting it returns a 404 or 410 status code).

Removing a page together is fine, but I would not want my website to return a 404. Each removed page shall have 301 redirects. This is important for the good positioning of our website and SEO.

Remove JobPosting structured data from the page.

If we don’t want to remove the page from our website but we just need to remove it from Google Job posting, the simplest way will be to change the jobPosting into false.

Once that is done, remember to request re-indexing of your job post URL in Search Console, so Google will be prompted about the change quicker, and don’t relay until Google bots will discover the change.

Testing JobPosting Schema #

Every schema, once put in place shall be checked for validity. Sometimes we may miss something, and here the Rich Result Test page comes in handy.


The above is just one of the examples of how to implement Schema into your website (in that instance JobPosting) and use shortcodes or partials, depending on how our website is designed.

Comments