Skip to the tool
OnPageKit

Job Posting Schema Generator

JobPosting JSON-LD with salary and remote rules.

required
required, simple HTML allowed
required, YYYY-MM-DD
recommended
employmentType recommended
required
required for on-site and hybrid
recommended
apply on this page?
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "JobPosting",
  "employmentType": "FULL_TIME"
}
</script>
  • No validThrough. Without an expiry date the listing can outlive the job it advertises.
  • No baseSalary. Google recommends it, and listings with pay are the ones people filter for.

Everything checked above is syntax and schema.org conformance. Whether the job appears in Google's job search experience is decided against the live page, so run the published URL through its Rich Results Test before counting on it.

Everything runs in your browser. Nothing you type is sent to a server.

Found a bug in this tool? Report it.

Share this tool

A job posting schema generator for Google for Jobs

This job posting schema generator writes the JobPosting JSON-LD that makes a vacancy eligible for the job search experience in Google, the panel usually called Google for Jobs. Fill in the role, the company, where the work happens and what it pays, and the block builds itself alongside. Nothing leaves your browser.

Job posting structured data has more rules that interact than most types. Two of them account for most rejected listings, and the form is built around both.

Where the work happens decides the location fields

An on-site role takes a jobLocation: a Place whose PostalAddress says where people report to, ideally down to the street, and at least the town and country. A fully remote role has no such place. It takes jobLocationType: "TELECOMMUTE" instead, and then Google requires applicantLocationRequirements, the countries a candidate may live in. A hybrid role takes both.

Choose the mode and the generator emits the matching combination. An office address left filled in on a remote role is dropped with a warning, because a remote job pinned to a street address is shown to commuters who will never be asked to commute.

Salary as MonetaryAmount

baseSalary is not a string such as "£48k–£60k". It is a MonetaryAmount with a three-letter currency, whose value is a QuantitativeValue. A range sets minValue and maxValue; a single figure sets value; both carry a unitText saying whether the number is per hour, day, week, month or year. Type plain numbers and the nesting is written for you. A maximum below the minimum, a thousands separator or a currency symbol in the amount are all caught before they reach the page.

Pay is only recommended, but in the job panel it is the filter candidates use first, and in several jurisdictions publishing it is a legal requirement anyway.

employmentType, validThrough and the rest

employmentType takes one or more fixed values: FULL_TIME, PART_TIME, CONTRACTOR, TEMPORARY, INTERN, VOLUNTEER, PER_DIEM or OTHER. Tick every one that applies; a single choice is written as a string and several as an array.

validThrough is the expiry. It is optional in the strict sense and the most useful field to set, because it retires the listing automatically when the closing date passes. The tool rejects an expiry that falls before datePosted.

The description accepts simple HTML, paragraphs and lists, since that is how the full job text is meant to arrive. Closing tags are escaped in the jobposting JSON-LD output so they cannot end the surrounding script element early.

What this checks, and what Google checks

The panel on the right covers syntax, value formats and the fields Google marks as required or recommended. Eligibility for the job experience is judged on the live page, including whether the markup matches the visible text. Test the published URL with Google's Rich Results Test, or lint the block here with the structured data validator. The hiring company deserves its own markup too: the organization schema generator covers it, and the local business schema generator covers a branch people visit.

Frequently asked questions

Which JobPosting fields does Google require?

Five: title, description, datePosted, hiringOrganization and jobLocation. The last one has an exception, a fully remote job, which replaces it with jobLocationType TELECOMMUTE plus applicantLocationRequirements. baseSalary, employmentType, validThrough, identifier and directApply are recommended.

How do I mark up a remote job in schema?

Set jobLocationType to TELECOMMUTE and list the countries people may work from in applicantLocationRequirements, one Country node each. Leave jobLocation out if there is no office to report to. For a hybrid role keep both: the office address and TELECOMMUTE together. Pick the mode in the form and the generator emits the right combination.

How should a salary range be written?

As a MonetaryAmount with an ISO 4217 currency, whose value is a QuantitativeValue carrying minValue, maxValue and a unitText of HOUR, DAY, WEEK, MONTH or YEAR. A single figure uses value instead of the pair. Numbers go in plain, with no currency symbol and no thousands separator.

What happens when the job is filled?

Take the markup down, or the page, and ideally set validThrough in advance so the listing expires on its own. Google treats expired jobs still marked up as a quality problem, and job seekers who apply to a closed role do not come back.

Does anything I type get uploaded?

No. The JSON-LD is assembled in this browser tab and nothing is sent or stored. Salary figures and internal references stay on your machine.

Related tools

Updated