Articles

Apr 28, 2026 / SEO & Growth / 8 min read

Job Posting Schema for Google for Jobs

If your job postings have valid schema but still aren't appearing in Google for Jobs, the fix usually isn't in your JSON-LD at all. Google needs to trust the real page first. Here is exactly how to structure your job pages, avoid duplicate content penalties, and write structured data that actually ranks.

Quick Answer

JobPosting schema only works when it exactly watches the visible details on a single, public job page. If your page validates but still isn't getting indexed, you don't need another schema field. You need to fix the URL structure, remove expired jobs faster, or ensure the visible data perfectly mirrors your JSON-LD.

Before adding more schema, check these 5 things first:

  • Make sure each job has exactly one canonical detail URL.
  • Make sure you aren't adding JobPosting tags to search or category pages.
  • Check that the visible title, employer, and location match the markup.
  • Make sure remote jobs have explicit location requirements.
  • Remove schema markup from jobs the moment they expire.

Start With the Page, Not the Schema

Google for Jobs is a search engine for web pages, not just a reader for JSON snippets. If a job page is thin, hard to read, or duplicated across several URLs on your domain, perfectly formatted JSON-LD won't save it.

The golden rule: If a human candidate cannot instantly figure out the role, the employer, the location, and how to apply, Google won't figure it out either. Fix the page UX before you tweak the schema.

  • One job, one URL: Every listing needs a single, definitive detail page to be indexed.
  • Visible facts are mandatory: Title, employer, location, and the apply button must be obvious on load.
  • Data must match: If the visible page says one thing and the JSON-LD says another, Google loses trust immediately.
  • Clean up fast: Leaving schema on expired jobs is the #1 way to slowly destroy indexation quality over time.
Structured data helps, but the page still needs to make sense to a human reader first.
Example job page with visible role, location, and apply path

Structured data helps, but the page still needs to make sense to a human reader first.

A Quick Audit Before Changing Code

Before rewriting your JSON-LD, it's worth checking a live job page from a candidate's perspective. Many "schema problems" are actually just page structure issues.

  1. Load a live job URL. Ensure it's a dedicated detail page, not a filtered search results page.
  2. Check for clarity. Are the role, employer, location, and apply button immediately obvious?
  3. Compare the page to the markup. If the title, location, or salary on the screen don't match the schema data, fix the mismatch first.
  4. Verify indexability. Make sure the URL is public, canonical, and not blocked by a `noindex` tag or a `robots.txt` file.
  5. Check for stale jobs. If a job is closed but the page still looks active, Google's trust in the site can drop.
  6. Watch for duplicate pages. Search filters or partner integrations often create multiple URLs for the exact same job post.

The Fields That Actually Matter

You don't necessarily need to fill out every optional structured data field right away. The key is to start with a reliable baseline that stays accurate as jobs are added and removed.

FieldUse it whenCommon mistake
titleAlwaysUse the real role title only. Do not stuff city, salary, or promo copy into it.
descriptionAlwaysIt must match the visible page and include a real, complete job description.
datePostedAlwaysUse the real posting date in ISO format, not an arbitrary refresh timestamp.
hiringOrganizationAlwaysUse the actual employer or authorized hiring entity, not a vague label.
jobLocationFor physical or hybrid rolesProvide real address detail, especially locality, region, and country.
jobLocationType + applicantLocationRequirementsFor fully remote rolesUse TELECOMMUTE only for jobs that are truly fully remote and define the allowed work locations.
validThroughWhen the job has a real expiry dateDo not invent one. If the job expires, update or remove it quickly.
baseSalaryWhen the employer provides salary dataOnly include salary if it is real and visible on the page.

A good rule of thumb: if a detail isn't visible on the webpage, don't try to cram it into the schema. This is especially true for salaries, remote policies, expiry dates, and employer names.

Handling Remote, Hybrid, and On-Site Jobs

Remote jobs often cause confusion with schema. If a role is fully remote, the jobLocationType should be TELECOMMUTE, and you should use applicantLocationRequirements to outline where the applicant is allowed to live.

Hybrid jobs are handled differently. If an employee is required to come to an office occasionally, the physical location still matters and should be treated like an on-site role in the schema.

  • Fully remote: Use TELECOMMUTE and clearly define the allowed country or region.
  • Hybrid: Use the real office location and explain the remote-work flexibility in the normal page text.
  • On-site: Use the exact physical location, including the city, region, and country.

Avoid marking a job as TELECOMMUTE just because the employer offers a few work-from-home days. Google treats TELECOMMUTE as fully remote, and getting that wrong can lead to poor candidate experiences and reduced search visibility.

Expired Jobs and Duplicate URLs

Leaving active JobPosting schema on closed jobs is a quick way to lose Google's trust. Cleaning up expired jobs is just as important as publishing them.

  • If the job is permanently gone, return a 404 or 410 status code.
  • If you want to keep the page live for archival purposes, remove the JobPosting markup.
  • If you know exactly when a job will close, use the validThrough property and make sure it has expired.

Duplicate URLs are another common gotcha. If the exact same listing is accessible via search parameters, category pages, or alternate domains, pick one definitive URL and set a canonical tag pointing to it.

A Simple JSON-LD Example

Here is a clean, minimal starting point. The goal isn't to stuff every possible property into the code, but to ensure the data perfectly mirrors what the visitor sees.

job-posting.jsonld
{
  "@context": "https://schema.org",
  "@type": "JobPosting",
  "title": "Senior Climate Data Engineer",
  "description": "<p>Build data pipelines for climate risk products...</p>",
  "datePosted": "2026-04-28",
  "employmentType": "FULL_TIME",
  "hiringOrganization": {
    "@type": "Organization",
    "name": "Example Climate Co",
    "sameAs": "https://example.com"
  },
  "jobLocationType": "TELECOMMUTE",
  "applicantLocationRequirements": {
    "@type": "Country",
    "name": "USA"
  }
}

Why Valid Pages Still Might Not Show Up

Sometimes a page passes the Rich Results Test with flying colors, but the job still doesn't appear. That usually means the issue lies outside the code snippet itself.

What you seeUsually meansFix first
The Rich Results Test passes but nothing shows in Google for JobsThe page is thin, duplicate, or not the canonical job URLCheck page quality, canonicals, and duplicate job paths before touching the schema again
Remote jobs behave inconsistentlyTELECOMMUTE is being used on hybrid jobs or without applicant location rulesSplit fully remote logic from hybrid logic in the template
Old jobs keep surfacing or quality drops over timeExpired jobs stay live with active JobPosting markupRemove the markup or remove the page quickly when jobs close
Only some jobs become eligibleThe page content and JSON-LD are generated from different data or updated at different timesMake the visible page and the markup come from the same record
Google crawls the page but still does not trust itCritical details are missing, hidden, or inconsistent on the visible pageMake title, employer, location, and apply path obvious without interaction

It helps to start by confirming the page quality and checking for duplicate URLs before spending time refining the schema syntax.

A Simple Validation Workflow

Rather than just checking for syntax errors, it's best to verify exactly what Google is seeing.

  1. Test the live URL. Run the actual web page through the Rich Results Test, rather than just pasting code.
  2. Check Search Console. Ensure Google isn't blocking or misinterpreting the page.
  3. Compare text and schema. Ensure your titles, locations, and salaries match on both sides.
  4. Check for duplicates. Ensure there isn't another version of the page competing for indexing.
  5. Verify expired listings. Make sure closed roles don't still look active.
  6. Use the Indexing API. Notify Google when a job opens, changes, or closes.

If you want to look at the bigger picture, you might find our Job Board SEO vs. General SEO comparison helpful.

Need job boards that handle schema automatically?

Kardow gives you indexable job pages and automated schema that stays perfectly in sync as jobs open, update, and expire.

Launch in hours
SEO-ready pages
Charge employers

Frequently Asked Questions

Is valid schema enough to appear in Google for Jobs?

No. Valid schema is only the starting point. Google also cares about page quality, canonical URLs, visible job details, stale-job handling, and whether the markup matches what users can actually see.

Should I add JobPosting schema to job category pages?

No. JobPosting belongs on the single job detail page. Category, search, and result pages should not contain individual JobPosting entities.

What should I do when a job expires?

Either remove the page so it returns a 404 or 410, remove the JobPosting markup, or ensure validThrough is in the past. Then notify Google with the Indexing API and keep your sitemap accurate.

How do I mark up remote jobs correctly?

Use jobLocationType set to TELECOMMUTE only for fully remote roles and specify applicantLocationRequirements so Google understands where applicants are allowed to work from.

Why do schema-valid pages still fail?

Usually because the problem is operational, not syntactic: duplicate URLs, weak canonicals, stale jobs, hidden content, thin job pages, or a mismatch between the markup and the visible page.

More articles

You may also like