Articles

Aug 6, 2026 / SEO & Growth / 9 min read

Job Posting Structured Data, Explained From Scratch

If you have been told your job pages need structured data, or markup, or schema, and you are not entirely sure those are three names for the same thing, this page is for you. They are. Here is what it means, why job pages specifically care, and how to add it in about ten minutes.

What Structured Data Actually Is

A person reading one of your job pages can tell at a glance that Acme Corp is the employer, Austin is the location, and $150,000 is the salary. They work it out from layout, wording, and context without thinking about it.

A search engine is inferring all of that from raw text, and inference is unreliable. Is "Austin" the city, or the hiring manager's name? Is that figure a salary or a budget the role manages?

Structured data settles it. You attach a small block of code to the page that labels each fact explicitly: this string is the job title, this one is the employer, this is the city. It is not visible to visitors and it does not change how the page looks. It exists purely so machines stop guessing.

The one-line version

Structured data is a labelled summary of facts already on your page, written where only machines read it. It adds no new information for humans. It removes ambiguity for search engines.

The Words People Use Interchangeably

Most of the difficulty here is vocabulary rather than technology. Six terms get used loosely, three of them mean the same thing, and nobody says which is which. Worth ten seconds:

TermWhat it actually refers toSame thing as?
Structured dataThe general idea: extra machine-readable information describing what a page is about.Yes, people use this interchangeably with "schema" and "markup".
Schema.orgThe shared vocabulary that defines the types and property names, such as JobPosting and hiringOrganization. A dictionary, not a file format.Often shortened to just "schema", which is where the confusion starts.
MarkupThe actual code you add to the page.Yes, same thing again. "Add job posting markup" means "add structured data".
JSON-LDOne of three formats for writing it. A block of JSON in a script tag. The other two, Microdata and RDFa, weave attributes into your HTML.No. This is a format choice. Google recommends JSON-LD.
Rich resultsWhat you might get back: the enhanced listings Google can show when it trusts your structured data.No. This is the outcome, not the code.
Google for JobsThe specific job search experience that JobPosting structured data can make you eligible for.No. It is one destination that reads your markup.

So "add job posting markup", "implement JobPosting schema", and "put structured data on your job pages" are three ways of asking for one task. If you have been reading conflicting guides, that alone may be why they seemed to disagree.

Why Job Pages Specifically Need It

For most page types structured data is optional polish. For job postings it is closer to a prerequisite, because it is the entry condition for Google for Jobs, the job search box that appears above normal results for hiring queries.

Google populates that box from pages carrying valid JobPosting structured data. No markup means no consideration, regardless of how good the page is. That is the practical reason job boards and careers pages treat this as mandatory while a blog might never bother.

What It Looks Like

Here is a complete, valid example with nothing optional in it. If you copied this into a job page and changed the values, you would have working structured data.

job-page-head.html
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "JobPosting",
  "title": "Senior Software Engineer",
  "description": "<p>We are hiring a senior engineer to...</p>",
  "datePosted": "2026-08-06",
  "hiringOrganization": {
    "@type": "Organization",
    "name": "Acme Corp"
  },
  "jobLocation": {
    "@type": "Place",
    "address": {
      "@type": "PostalAddress",
      "addressLocality": "Austin",
      "addressRegion": "TX",
      "addressCountry": "US"
    }
  }
}
</script>

Reading it: @context says which vocabulary you are using, always schema.org. @type says what kind of thing the page describes, here a JobPosting. Everything after that is a labelled fact. The nested objects exist because an employer and an address are things in their own right rather than plain strings, which is why hiringOrganization takes an object with a name rather than just the company name directly.

The Five Fields Google Requires

Google lists exactly five required properties on a JobPosting. Miss any and the listing is unlikely to appear at all. Everything else it publishes, including salary, employment type, and expiry date, is recommended, so leaving those out produces a warning rather than an error.

PropertyIn plain termsExample value
titleThe job title, as a candidate would search itSenior Software Engineer
descriptionThe full job description, not a summaryThe complete posting text, as HTML
datePostedWhen the job actually went live2026-08-06
hiringOrganizationWho is hiring, as an object rather than a plain stringAcme Corp
jobLocationWhere the job is. Fully remote roles answer this differently, see below.Austin, TX, US

Two of these cause nearly all the trouble. description must be the full job description rather than a teaser, and it must match what the page shows. And title must be the actual job title, not the headline of your advert. Google's wording on that is blunt: the title of the job, not the title of the posting. If your listings carry titles like "Join Our Amazing Team", that is a real problem with a real cost, covered in job title schema markup.

Handling Remote Jobs

The one case where the five-field rule needs qualifying. A fully remote job has no physical jobLocation, so instead of an address you supply two properties saying it is remote and where applicants may be based:

remote-job.jsonld
"jobLocationType": "TELECOMMUTE",
"applicantLocationRequirements": {
  "@type": "Country",
  "name": "US"
}

Use TELECOMMUTE only for genuinely fully remote roles. A hybrid job that expects someone in the office two days a week is an on-site job as far as the markup is concerned, and should carry the real office address.

Build Yours

Rather than editing the example by hand, fill in the fields below. It builds the same structure, handles the remote and on-site branches for you, and runs entirely in your browser.

Free JobPosting schema generator

Fill in the fields. Valid JSON-LD updates live. No sign-up, runs in your browser.

Only add salary if it is real and visible on the job page.

job-posting.jsonld

Copy the <script> tag into the <head> of one job page, then follow the check in the next section. The generator also lives on its own page at the job posting schema generator if you want to come back to it.

Checking That It Worked

Publish the page first, then run the live URL through Google's Rich Results Test. Testing the URL rather than pasting the snippet matters: it is the only way to confirm Googlebot can actually see the markup on the rendered page, which is exactly what fails when content is injected by JavaScript after load.

A pass tells you the syntax is correct and the required properties are present. Warnings about missing recommended properties are fine to leave for now. Errors are not, and each message maps to a specific cause in the Google for Jobs error reference.

When It Validates but Nothing Happens

This is where a lot of people get stuck, and it is worth knowing in advance that it is normal rather than a sign you did something wrong. Valid markup makes a job eligible for Google for Jobs. It does not oblige Google to show it.

Once your markup validates, the remaining questions are about the page rather than the code: whether each job has one canonical URL, whether closed jobs are being retired promptly, whether the visible page backs up every claim in the markup. That is a different problem from this one, and it has its own guide in why valid JobPosting schema still does not appear in Google for Jobs. Start there once the Rich Results Test is green.

Or skip the markup entirely

A job board platform should emit valid JobPosting structured data on every listing and retire it when a job closes, without anyone editing head tags. Kardow does this for every job page it publishes.

Launch in hours
SEO-ready pages
Charge employers

Frequently Asked Questions

What is structured data in simple terms?

It is a short, machine-readable summary you attach to a page describing what the page contains. A human reading your job page can tell that "Acme Corp" is the employer and "Austin" is the location. A search engine is only guessing at that from the text. Structured data removes the guessing by labelling each fact explicitly, using a shared vocabulary called schema.org that every major search engine understands.

Is job posting markup the same as job posting schema?

Yes. Structured data, markup, and schema are used interchangeably for the same thing in this context, which is a large part of why the topic feels harder than it is. JSON-LD is different: that is the format you write it in, and it is the one Google recommends.

Do I need to add structured data to every job page?

Yes, one JobPosting block on each individual job detail page. Do not put it on your homepage, on category pages, or on search results pages. Google reads the markup per URL, so a single page listing twenty jobs is not the right place for it, and marking up a list page is a common reason listings never become eligible.

What are the required fields for job posting structured data?

Google requires five: title, description, datePosted, hiringOrganization, and jobLocation. Fully remote roles satisfy the location requirement with jobLocationType set to TELECOMMUTE plus applicantLocationRequirements instead of a physical address. Everything else, including salary, employment type, and expiry date, is recommended rather than required.

Where exactly do I paste the code?

Inside the head section of the individual job page, as a script tag with the type attribute set to application/ld+json. It works in the body too, but the head is conventional and easier to audit. If you use a CMS, look for a setting that injects custom code into the head of a single page or post.

How do I know if it worked?

Run the live URL, not a pasted snippet, through Google's Rich Results Test. Testing the live URL is what tells you whether Googlebot can actually see the markup, which matters when content is rendered by JavaScript. A pass means the syntax is right. It does not mean the job will appear, because eligibility depends on page quality factors as well.

More articles

You may also like