Complete Guide to Job Posting Schema for Google Jobs (2026)

Complete Guide to JobPosting Schema for Google Jobs (2026) | WPNova
Updated for 2026

Everything you need to implement schema.org/JobPosting correctly — from required fields to salary markup, remote jobs, WordPress integration, and passing Google's Rich Results Test first time.

By WPNova Editorial Team
Published Jan 10, 2026
Updated Jun 1, 2026
20 min read
4,800 words

What You'll Learn

  • What JobPosting schema is and how it works
  • All required & recommended properties for 2026
  • Full working JSON-LD code with explanations
  • How to mark up remote jobs and salary ranges
  • WordPress implementation with plugins and manual code
  • Common errors and how to fix each one
  • Do's and don'ts that Google explicitly checks
  • How to validate and monitor in Search Console
2.4× More clicks on listings with Google Jobs rich results vs. standard blue links
40% Of job seekers discover listings through Google Search every month
4 Required properties — miss any one and the rich result is suppressed entirely

What Is JobPosting Schema Markup?

JobPosting schema is structured data you add to a job listing page using the schema.org/JobPosting vocabulary. Written as a JSON-LD script block in your page's HTML, it gives Google a machine-readable description of every important detail in the job ad — the title, description, employer, location, salary, employment type, and more.

When Google's crawler finds correctly implemented JobPosting schema, it can surface that listing directly inside the Google Jobs experience — the dedicated job-search interface that appears at the top of relevant search results pages. This is also sometimes called a job posting rich result.

ℹ️

JSON-LD vs Microdata vs RDFa: Google supports all three formats, but officially recommends JSON-LD for structured data. All examples in this guide use JSON-LD because it's easiest to maintain — it lives in a script block and never needs to be woven into your HTML markup.

How Google Jobs Works

Google Jobs is not a separate website — it's a feature built into Google Search. When a user searches for a job-related query like "software engineer jobs remote" or "marketing manager jobs London," Google may surface a dedicated Jobs panel above or alongside standard results, populated entirely from structured data it has crawled from employers' and job boards' websites.

Your job listings compete in this panel based on schema completeness, data freshness, page quality, and other algorithmic signals. Schema is the entry point — without it, you simply cannot appear, no matter how great the page is.

Why JobPosting Schema Matters More in 2026

The stakes for correct implementation have risen considerably in 2026 for three reasons:

  • AI Overviews now reference Google Jobs data. Google's AI-generated answer cards for job searches pull structured data directly. If your schema is wrong or missing, your listings are invisible in AI search too.
  • Google is stricter about spam. In 2025, Google updated its job posting content policies to penalize misleading salary data, vague descriptions, and listings without proper validThrough dates. Violating these can get your entire domain demoted.
  • Direct competition from aggregators. Indeed, LinkedIn, and Glassdoor all implement schema perfectly. If you don't, you lose clicks to aggregators even for your own job listings.
⚠️

New in 2026: Google now penalizes listings where the validThrough date has passed but the job is still indexed. Always set accurate expiry dates and unpublish filled roles promptly.

Required Properties (2026)

Google will not show a rich result for any job posting that is missing one or more of these four properties. They are non-negotiable.

Property Type Status What Google Expects
title Text Required The job title exactly as it appears in the listing. Don't stuff keywords here — Google will suppress it.
description Text / HTML Required Full job description. Supports basic HTML (<p>, <ul>, <strong>). Must be substantive — not a summary.
hiringOrganization Organization Required Employer details: name and ideally sameAs (company website URL) and logo.
jobLocation Place Required* Physical work location with a full PostalAddress. *Remote-only roles use jobLocationType instead — see section below.

Also treat as required: datePosted and validThrough. Technically recommended by schema.org, Google's guidance states listings without datePosted are ranked lower and those without validThrough are removed from Google Jobs after a default period.

The more complete your schema, the better Google understands the listing — and the better it performs in search. These properties are optional but strongly recommended.

datePosted
Date (ISO 8601)

When the listing was published. Affects freshness ranking. Use ISO format: 2026-06-01.

validThrough
DateTime (ISO 8601)

When the listing expires. Critical — Google removes listings after this date. Use with time: 2026-07-01T23:59:59.

employmentType
Text (enum)

Values: FULL_TIME, PART_TIME, CONTRACTOR, TEMPORARY, INTERN, VOLUNTEER, PER_DIEM, OTHER. Can be an array.

baseSalary
MonetaryAmount

Salary with currency, min/max values, and pay period (HOUR, WEEK, MONTH, YEAR). Strongly correlated with click-through rate.

jobLocationType
Text (enum)

Use TELECOMMUTE for remote roles. Must be combined with applicantLocationRequirements for geo-restricted remote jobs.

applicantLocationRequirements
AdministrativeArea

Geographic requirement for remote applicants. Specify country, state, or region using Country, State, or City schema types.

directApply
Boolean

Set to true if applicants can apply directly on your page without going to a third-party ATS. Eligible for Google's "Direct Apply" badge.

identifier
PropertyValue

Your internal job ID. Helps Google deduplicate across aggregators. Use name (your company) and value (the job ID).

experienceRequirements
Text / OccupationalExperienceRequirements

Years of experience required. Text or structured with monthsOfExperience.

educationRequirements
Text / EducationalOccupationalCredential

Minimum education level. Can use a text string or structured credential type with credentialCategory.

skills
Text

Required skills as a comma-separated string or multiple instances. Helps with semantic matching in AI-powered search results.

jobBenefits
Text

Perks and benefits. Increasingly surfaced in Google's AI Overviews for job searches when well-structured.

Full JobPosting Schema Code Example

Here is a complete, production-ready JobPosting JSON-LD block with all required and recommended properties. Copy this and replace the placeholder values with your own data.

JSON-LD — Complete JobPosting Schema
// Add this inside <script type="application/ld+json"></script> in your page <head>
{
  "@context": "https://schema.org",
  "@type": "JobPosting",

  // ─── Required Properties ───────────────────────────────────────

  "title": "Senior Frontend Developer",

  "description": "<p>We are looking for a Senior Frontend Developer to join our product team. You will build responsive, high-performance web applications using React and TypeScript.</p><ul><li>5+ years of experience with React</li><li>Strong TypeScript skills</li><li>Experience with REST APIs and GraphQL</li></ul>",

  "hiringOrganization": {
    "@type": "Organization",
    "name": "Acme Corp",
    "sameAs": "https://www.acmecorp.com",
    "logo": "https://www.acmecorp.com/images/logo.png"
  },

  "jobLocation": {
    "@type": "Place",
    "address": {
      "@type": "PostalAddress",
      "streetAddress": "123 Tech Street",
      "addressLocality": "San Francisco",
      "addressRegion": "CA",
      "postalCode": "94105",
      "addressCountry": "US"
    }
  },

  // ─── Strongly Recommended ──────────────────────────────────────

  "datePosted": "2026-06-01",
  "validThrough": "2026-07-31T23:59:59",

  "employmentType": ["FULL_TIME"],

  "baseSalary": {
    "@type": "MonetaryAmount",
    "currency": "USD",
    "value": {
      "@type": "QuantitativeValue",
      "minValue": 120000,
      "maxValue": 160000,
      "unitText": "YEAR"
    }
  },

  "identifier": {
    "@type": "PropertyValue",
    "name": "Acme Corp",
    "value": "JOB-2026-0042"
  },

  // ─── Optional but Valuable ─────────────────────────────────────

  "directApply": true,

  "workHours": "Monday–Friday, 9am–5pm PST",

  "experienceRequirements": {
    "@type": "OccupationalExperienceRequirements",
    "monthsOfExperience": 60
  },

  "educationRequirements": {
    "@type": "EducationalOccupationalCredential",
    "credentialCategory": "bachelor degree"
  },

  "skills": "React, TypeScript, GraphQL, REST API, CSS, HTML5, Git",

  "jobBenefits": "Health insurance, 401(k) matching, unlimited PTO, remote-friendly, annual learning stipend",

  "industry": "Software Development",

  "occupationalCategory": "15-1254.00"  // O*NET code for Web Developers
}

Remote Job Schema: The Right Way

Remote jobs have their own schema requirements. You cannot simply set jobLocation to "Remote" as a text string — Google will reject this. Use the pattern below.

Fully Remote (No Geographic Restriction)

JSON-LD — Fully Remote Job
{
  "@context": "https://schema.org",
  "@type": "JobPosting",
  "title": "Content Strategist",
  "jobLocationType": "TELECOMMUTE",
  // No jobLocation required for fully remote roles with no restrictions
  "applicantLocationRequirements": {
    "@type": "Country",
    "name": "US"  // Hire anywhere in US
  },
  "hiringOrganization": {
    "@type": "Organization",
    "name": "Acme Corp",
    "sameAs": "https://www.acmecorp.com"
  },
  "description": "...",
  "datePosted": "2026-06-01",
  "validThrough": "2026-08-01"
}

Hybrid (On-site + Remote Option)

JSON-LD — Hybrid Job
{
  "@context": "https://schema.org",
  "@type": "JobPosting",
  "title": "Product Manager",
  "jobLocationType": "TELECOMMUTE",
  "jobLocation": {
    "@type": "Place",
    "address": {
      "@type": "PostalAddress",
      "addressLocality": "Austin",
      "addressRegion": "TX",
      "addressCountry": "US"
    }
  },
  // Both jobLocationType AND jobLocation = hybrid signal to Google
  "hiringOrganization": { "..." },
  "description": "..."
}

Salary Markup: Formats Google Accepts

Salary transparency is one of the most impactful things you can add to your schema. Google's research shows that listings with salary data get significantly more engagement in the Jobs panel. Here's every salary format Google supports.

Salary Format unitText Value Example Schema Value Notes
Hourly HOUR minValue: 25, maxValue: 35 Common for part-time / contractor
Weekly WEEK minValue: 1000, maxValue: 1500 Less common; prefer MONTH or YEAR
Monthly MONTH minValue: 4000, maxValue: 6000 Standard in many markets outside US
Annual YEAR minValue: 80000, maxValue: 110000 Most common for full-time roles
💡

Best practice: Always provide a salary range (minValue + maxValue) rather than a single value. Google's display format favors ranges and they correspond better to how candidates search. Never set an inflated max to attract attention — Google's spam team flags unrealistic ranges.

How to Implement JobPosting Schema

Option 1: Manual JSON-LD

If you're not using a CMS plugin, add the JSON-LD block directly to your job listing page template. Place it in the <head> or anywhere in the <body> before </body>.

1

Create the JSON-LD block

Start from the full example above and populate each field with your listing's real data. Don't use placeholder text — Google may flag descriptions with generic content.

2

Wrap in a script tag

Wrap your JSON object in <script type="application/ld+json"></script>. The type attribute is mandatory and must be exactly application/ld+json.

3

Add it to your page template

In a custom PHP template, echo the script block dynamically using your job's data fields. In static HTML, paste it directly into the page.

4

Test with Google Rich Results Test

Go to search.google.com/test/rich-results. Paste your URL or the raw code. It will tell you if you have a valid JobPosting rich result or show specific errors to fix.

5

Monitor in Google Search Console

After Google crawls your pages, go to Search Console → Enhancements → Job postings. You'll see the count of valid items and any warnings or errors requiring attention.

Option 2: WordPress Implementation

WordPress users have several options for adding JobPosting schema depending on their setup:

Method Best For Schema Control Difficulty
WP Job Manager plugin Full job board sites Automatic, highly configurable Easy
Yoast SEO + Local SEO Sites using Yoast already Good but limited salary control Easy
Rank Math Schema Builder Power users wanting full control Full property control per listing Medium
Schema Pro plugin Any WordPress site, rule-based Full; bulk schema rules Medium
WPNova Job Board Plugin New job boards wanting best-in-class SEO Native schema with all 2026 properties including salary, remote, directApply Easy
Custom code (functions.php) Developers who need full control Total control Advanced

WordPress Custom Code (functions.php)

If you manage jobs as a custom post type, add schema dynamically using this pattern in your theme's functions.php or a custom plugin:

PHP — WordPress functions.php
function wpnova_add_jobposting_schema() {
  if ( !is_singular('job_listing') ) return;

  $post_id = get_the_ID();
  $title   = get_the_title();
  $desc    = wp_strip_all_tags( get_the_content() );
  $date    = get_the_date( 'Y-m-d' );
  $expiry  = get_post_meta( $post_id, '_job_expires', true );

  $schema = [
    '@context'          => 'https://schema.org',
    '@type'             => 'JobPosting',
    'title'             => esc_html( $title ),
    'description'       => esc_html( $desc ),
    'datePosted'        => $date,
    'validThrough'      => $expiry ? $expiry . 'T23:59:59' : '',
    'hiringOrganization' => [
      '@type'  => 'Organization',
      'name'   => get_bloginfo( 'name' ),
      'sameAs' => get_bloginfo( 'url' ),
    ],
    'jobLocation' => [
      '@type'   => 'Place',
      'address' => [
        '@type'           => 'PostalAddress',
        'addressLocality' => get_post_meta( $post_id, '_job_location', true ),
        'addressCountry'  => get_post_meta( $post_id, '_job_country', true ),
      ],
    ],
  ];

  echo '<script type="application/ld+json">'
    . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE )
    . '</script>';
}
add_action( 'wp_head', 'wpnova_add_jobposting_schema' );

Common Errors and How to Fix Them

These are the most frequent issues flagged by the Rich Results Test and Google Search Console. Fixing them is usually straightforward once you know what Google expects.

Error Message Cause Fix
"Missing field 'description'" The description property is absent or empty Add a substantive description with at least several sentences. Cannot be blank or a single word.
"Missing field 'hiringOrganization'" Employer name not provided Add hiringOrganization with at minimum @type: Organization and name.
"Invalid value for 'employmentType'" Using non-standard values like "Full Time" (with a space) or "Permanent" Use only Google's accepted enum values: FULL_TIME, PART_TIME, CONTRACTOR, etc.
"Either 'jobLocation' or 'jobLocationType' is required" Both are missing; location is undefined Add a physical jobLocation address, or set jobLocationType: TELECOMMUTE for remote jobs.
"Invalid date format for 'datePosted'" Using a format like "June 1, 2026" or "01/06/2026" Use ISO 8601 format: 2026-06-01
"Salary value must be a number" Using a string like "$80,000" instead of a numeric value Set minValue and maxValue as plain numbers: 80000, not "$80,000". Currency goes in the currency field.
"Value of 'unitText' must be one of..." Using "Annual" or "Per Year" instead of the accepted enum Use uppercase enum: HOUR, WEEK, MONTH, or YEAR.
"Unparsable structured data" Invalid JSON — usually a trailing comma or missing quote Validate your JSON at jsonlint.com first, then re-test in Rich Results Test.

Do's and Don'ts: Google's Content Policies

Google explicitly penalizes schema that doesn't match the visible page content, contains misleading information, or tries to manipulate the system. These do's and don'ts are drawn directly from Google's job posting guidelines.

✓ Do This
  • Use the actual job title — no keyword stuffing ("Developer (Great Pay! Remote!)")
  • Match the salary in schema exactly to what's shown on the page
  • Set a real validThrough date and remove expired listings
  • Write a genuine description with duties, requirements, and company info
  • Use directApply: true only when users actually apply on your page
  • Keep datePosted as the original posting date — don't refresh it to game freshness
  • Ensure the job listing page is publicly accessible (no login required)
✗ Never Do This
  • Promote unrelated products or content in the job description
  • Show a salary range in schema but hide it behind a click or login on the page
  • Include hate speech, discriminatory language, or illegal requirements
  • Use validThrough dates far in the future to keep old listings visible
  • Add schema to pages that don't actually contain a job listing
  • Copy-paste a description that's identical across many listings
  • Block Googlebot from crawling your job listing pages

Frequently Asked Questions

What is JobPosting schema markup?
JobPosting schema markup is structured data using the schema.org/JobPosting vocabulary added to your web pages as JSON-LD. It tells Google exactly what your job listing contains — title, salary, location, employer — so Google can display it as a rich result inside the Google Jobs experience. Without it, your listing cannot appear in Google Jobs regardless of how well-optimised the page is.
What are the required properties for JobPosting schema in 2026?
Google requires four properties: title (the job title), description (full job description), hiringOrganization (employer details including name), and jobLocation (place of work — or jobLocationType: TELECOMMUTE for remote roles). Missing any one of these prevents the rich result entirely. Treating datePosted and validThrough as required is also strongly advised.
How do I add JobPosting schema in WordPress?
The easiest approach in WordPress is using a dedicated job board plugin that outputs schema natively (WP Job Manager, WPNova Job Board Plugin). Alternatively, use Rank Math or Schema Pro which offer full JobPosting schema control. For developers, output the JSON-LD dynamically from a custom post type using wp_head hook as shown in the code example above.
Does JobPosting schema guarantee appearance in Google Jobs?
No. Valid JobPosting schema makes your listing eligible for Google Jobs rich results — it removes the technical barrier. Whether Google actually surfaces your listing depends on additional algorithmic factors: page quality, freshness, indexability, content uniqueness, and how well the listing matches a user's search query. Schema is necessary but not sufficient on its own.
What salary format does Google require for JobPosting schema?
Salary must be marked up using the baseSalary property with a MonetaryAmount type containing: a currency (ISO 4217 code like USD, GBP, EUR), and a value of type QuantitativeValue with minValue, maxValue (both plain numbers — no $ symbols or commas), and unitText using one of: HOUR, WEEK, MONTH, or YEAR.
What is the difference between jobLocationType and jobLocation?
jobLocation is a Place type with a PostalAddress specifying the physical office or work location. jobLocationType is used for remote jobs and must be set to TELECOMMUTE — it's the only accepted value. For hybrid roles, include both. For fully remote with geographic restrictions, use jobLocationType: TELECOMMUTE plus applicantLocationRequirements with a Country, State, or City type.
Can I have multiple JobPosting schemas on one page?
Technically yes — you can include multiple JSON-LD blocks on a single page, each representing a different job. However, Google typically only surfaces one rich result per URL. For best results in Google Jobs, use individual job detail pages (one URL per job) with a single JobPosting schema block each, rather than a listings page with many schemas.
How often should I update my JobPosting structured data?
Update your schema whenever any detail changes (location, salary, title, deadline). Most importantly: always set an accurate validThrough date and remove or unpublish listings when the role is filled. Google actively removes expired listings from Google Jobs and penalises domains with consistently stale postings. Do not artificially refresh datePosted to game freshness signals.
Does JobPosting schema help with AI search results like Google's AI Overviews?
Yes. In 2026, Google's AI Overviews for job-related queries actively reference structured data from JobPosting schema to generate summaries of available roles, salary ranges, and employer details. Well-structured schema — particularly salary, skills, benefits, and clear employment type — increases the likelihood your listings are cited in AI-generated job search answers.

Official Resources & Tools

Use these authoritative tools and references to validate, monitor, and deepen your understanding of JobPosting schema.

Ready to Rank in Google Jobs?

The WPNova Job Board Plugin handles all JobPosting schema automatically — including salary, remote jobs, validThrough, and directApply. Zero manual coding required.