Job Posting Schema — JobPosting JSON-LD for Google's Job Search
JobPosting markup makes a job eligible for Google's job search experience. Google requires five properties, one job per page, and that you expire jobs once they're filled.
Generate JobPosting JSON-LDWhy job pages miss Google's job search
- The description is a one-line summary, but Google requires the full description in HTML.
- The title carries the company, city, or pay, which Google says must not be in title.
- A hybrid job is marked TELECOMMUTE, which Google reserves for jobs that are 100% remote.
- Filled jobs stay live with no validThrough in the past, which can lead to a manual action.
- JobPosting markup sits on the careers page that lists every opening, not on each job’s page.
How SwiftSchema helps
The generator asks for the five properties Google requires, takes a full HTML description, and offers Google’s case-sensitive employmentType and salary unit values as choices.
It handles on-site jobs (one or more addresses with a country) and fully remote jobs (TELECOMMUTE plus applicant location), and writes a salary as an exact amount or a min and max range.
What is JobPosting structured data?
JobPosting is the schema.org type for "a listing that describes a job opening in a certain organization." On a job's own page, it gives Google the title, description, employer, location, pay, and dates in a form it can read without guessing.
Google uses it for its job search experience in Search, where people can filter jobs by criteria such as location or job title, and see work-from-home jobs. To be eligible, a job needs the required properties below and has to follow Google's job posting content policies. Google doesn't guarantee that a job will be shown.
Required properties
Google lists five required properties. A job without them isn't eligible for the job search experience.
| Property | What Google requires |
|---|---|
title | The job's title only, such as "Software Engineer". No job codes, addresses, dates, salaries, or company names, and don't overuse special characters such as ! and *. Use title, not name. |
description | The full job description in HTML: responsibilities, qualifications, skills, working hours, and education and experience requirements. It can't be the same as the title. Google reads <p>, <ul>, and <li>. |
datePosted | The date the employer posted the job, in ISO 8601 format, such as 2026-10-13. |
hiringOrganization | The company offering the job, such as "Starbucks, Inc", not the hiring location. Use the value confidential for anonymous postings by staffing agencies. |
jobLocation | Where the employee reports to work, as a Place with a PostalAddress. addressCountry is required. List several places in an array if the job has several locations. |
For a job that is 100% remote, jobLocation isn't required if you use jobLocationType and applicantLocationRequirements instead (see below).
validThrough is listed as recommended, but Google notes it's required for job postings that have an expiration date.
Recommended properties
| Property | Notes |
|---|---|
validThrough | When the posting expires, in ISO 8601: a date such as 2026-11-30 or a date and time such as 2026-11-30T23:59:00-05:00. Leave it out if the job doesn't expire. |
employmentType | One or more of FULL_TIME, PART_TIME, CONTRACTOR, TEMPORARY, INTERN, VOLUNTEER, PER_DIEM, OTHER. The values are case-sensitive. |
baseSalary | The actual base salary from the employer, not an estimate. A MonetaryAmount with currency and a QuantitativeValue: either value, or minValue and maxValue for a range, and unitText of HOUR, DAY, WEEK, MONTH, or YEAR. |
jobLocationType | TELECOMMUTE, only for jobs that are 100% remote. |
applicantLocationRequirements | Where applicants may live for a remote job, such as a Country or State. Required when the job is 100% remote and limited to certain places. |
identifier | The employer's own ID for the job, as a PropertyValue. |
directApply | true if people can apply on your page without unnecessary steps. Google says it's still developing how it uses this. |
Google also lists three beta properties: educationRequirements (with a credentialCategory such as bachelor degree), experienceRequirements (with monthsOfExperience), and experienceInPlaceOfEducation. Google still requires the education and experience requirements in description; the last example above shows all three.
Remote and hybrid jobs
Use "jobLocationType": "TELECOMMUTE" only when the job is 100% remote, and say so in the description. Google says not to mark up jobs that allow occasional work from home, or where remote work is negotiable.
A remote job needs at least one country applicants may work from. Use applicantLocationRequirements (Google prefers it). If the job can also be done at an office, add that office as jobLocation. Without applicantLocationRequirements, Google shows the job to anyone in the jobLocation country.
Rules that get jobs removed
Google's job posting content policies, in short:
- One job per page. JobPosting can only be used on a page with a single job. Not on search results, category, or list pages.
- The markup is on the job page. It must be on the same page as the description people can read.
- No expired jobs. Remove the page, remove the markup, or set
validThroughin the past. Google says not doing this in time "may result in a manual action." - A way to apply. No career fair invitations, and no job details behind a login.
- No fake or misleading jobs, including jobs that mainly collect applicant data, keyword-stuffed titles, and false locations.
- No payment from applicants, no ads disguised as jobs, and no excessive ads on the page.
Keep Google up to date
For job posting URLs, Google recommends the Indexing API over sitemaps, because it gets Googlebot to crawl the page sooner. Use it when you add a job, change one, or remove one. Google still recommends a sitemap for the rest of your site.
How to build it here
- 01
Enter the job title only: no company name, location, or salary.
- 02
Paste the full description from the page, in HTML.
- 03
Set the date posted and, if the job closes on a date, Valid Through.
- 04
Pick the employment type, then add the hiring organization’s name, website, and logo.
- 05
Add each work location with its country, or tick 100% remote and enter the applicant country for a fully remote job.
- 06
Add the salary as an exact amount or a min and max range, with the currency and unit.
- 07
Copy the JSON-LD into the job’s page, then test the page in Google’s Rich Results Test.
Ready to build the markup?
One job per page. Expire it when it's filled.
The generator emits title, description, datePosted, validThrough, employmentType, hiringOrganization (name, website as sameAs, logo), jobLocation, jobLocationType, applicantLocationRequirements, directApply, and baseSalary (a single amount or a range). Empty fields are left out. For identifier or the beta education and experience properties, start from the examples above.
Common mistakes
- Company or location in
title. "Warehouse Associate", not "Warehouse Associate – Northstar – Richmond – $20/hr". - A one-line description. Google requires the full description, in HTML, and it can't repeat the title.
- No
addressCountry. Google requires it in everyjobLocation. - TELECOMMUTE on a hybrid job. It's only for jobs that are fully remote.
- Jobs left up after they're filled. Expire them and notify Google, or risk a manual action.
- JobPosting on the careers page that lists every opening. Mark up each job's own page instead.
- Lowercase values.
employmentTypeandunitTextare case-sensitive:FULL_TIME,YEAR.
Required properties
titledescription (HTML)datePostedhiringOrganizationjobLocation (or jobLocationType TELECOMMUTE with applicantLocationRequirements)
Recommended properties
validThrough (required if the job expires)employmentTypebaseSalaryapplicantLocationRequirementsjobLocationTypeidentifierdirectApplyeducationRequirements (beta)experienceRequirements (beta)experienceInPlaceOfEducation (beta)
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Shipping and Receiving Warehouse Associate",
"description": "<p>Northstar Supply is hiring a full-time warehouse associate for our Richmond distribution center.</p><ul><li>Receive, check, and put away inbound shipments</li><li>Pick and pack orders with a handheld scanner</li><li>Day shift, Monday to Friday, 7am to 3:30pm</li></ul><p>Requirements: high school diploma or equivalent, able to lift 50 lb. Apply on this page.</p>",
"identifier": {
"@type": "PropertyValue",
"name": "Northstar Supply",
"value": "WH-2026-114"
},
"datePosted": "2026-10-13",
"validThrough": "2026-11-30T23:59:00-05:00",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "Northstar Supply",
"sameAs": "https://www.example.com",
"logo": "https://www.example.com/images/logo-512.png"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"streetAddress": "2100 Example Pkwy",
"addressLocality": "Richmond",
"addressRegion": "VA",
"postalCode": "23224",
"addressCountry": "US"
}
},
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": {
"@type": "QuantitativeValue",
"minValue": 18.5,
"maxValue": 22,
"unitText": "HOUR"
}
},
"directApply": true
}{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Senior Frontend Engineer",
"description": "<p>This is a 100% remote role for applicants living in the United States.</p><ul><li>Build accessible UI components in React and TypeScript</li><li>Improve page performance and Core Web Vitals</li><li>Review code and mentor two engineers</li></ul><p>Requirements: 5+ years of frontend experience.</p>",
"datePosted": "2026-10-13",
"validThrough": "2026-12-15",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "Northstar Analytics",
"sameAs": "https://www.example.com"
},
"jobLocationType": "TELECOMMUTE",
"applicantLocationRequirements": {
"@type": "Country",
"name": "US"
},
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": {
"@type": "QuantitativeValue",
"minValue": 150000,
"maxValue": 180000,
"unitText": "YEAR"
}
}
}{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Software Engineer",
"description": "<p>Build internal tools for our operations team.</p><p>Requirements: a bachelor's degree and 3 years of experience, or 5 years of experience in place of the degree.</p>",
"datePosted": "2026-10-13",
"hiringOrganization": {
"@type": "Organization",
"name": "Northstar Analytics",
"sameAs": "https://www.example.com"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Richmond",
"addressRegion": "VA",
"addressCountry": "US"
}
},
"educationRequirements": {
"@type": "EducationalOccupationalCredential",
"credentialCategory": "bachelor degree"
},
"experienceRequirements": {
"@type": "OccupationalExperienceRequirements",
"monthsOfExperience": 36
},
"experienceInPlaceOfEducation": true
}FAQs
Which JobPosting properties does Google require?ShowHide
Five: title, description, datePosted, hiringOrganization, and jobLocation. For a 100% remote job, use jobLocationType set to TELECOMMUTE with applicantLocationRequirements instead of jobLocation. validThrough is also required when the job has an expiration date.
Does JobPosting markup guarantee my job appears in Google?ShowHide
No. The required properties make a job eligible for Google's job search experience. Google says it doesn't guarantee that features using structured data will appear, and its job posting content policies also apply.
How do I mark up a remote job?ShowHide
Set jobLocationType to TELECOMMUTE, say in the description that the job is 100% remote, and list where applicants may live with applicantLocationRequirements (at least one country). Don't use TELECOMMUTE for hybrid jobs or jobs with occasional work from home.
How do I add a salary range?ShowHide
Use baseSalary with a MonetaryAmount whose value is a QuantitativeValue with minValue and maxValue, plus unitText of HOUR, DAY, WEEK, MONTH, or YEAR. Google says only employers can provide baseSalary.
Does validThrough need a time and timezone?ShowHide
No. Google accepts any ISO 8601 date, such as 2026-11-30 or 2026-11-30T23:59:00-05:00. Leave validThrough out if the job never expires or you don't know when it will.
What should happen when a job is filled?ShowHide
Remove the page (404 or 410), remove the JobPosting markup, or set validThrough to a date in the past. Then tell Google: it recommends the Indexing API for job posting URLs. Google says failing to expire jobs in time may result in a manual action.
Can I put JobPosting on a careers page that lists many jobs?ShowHide
No. Google only allows JobPosting markup on a page with a single job posting, and the markup must be on the same page as the job description people read.