Job listings without schema markup remain invisible to Google for Jobs, the dedicated job search experience that surfaces positions directly in search results. For recruiters and HR teams, JobPosting schema determines whether open positions appear in Google’s job carousel or get buried beneath aggregator sites.
This guide covers the complete JobPosting schema implementation: required properties that trigger eligibility, recommended fields that improve visibility, remote job considerations, salary transparency, and the critical expiration handling that prevents outdated listings from damaging your site’s structured data quality.
How JobPosting Schema Enables Google for Jobs
Google for Jobs aggregates job listings from across the web into a unified search experience. When someone searches for “marketing manager jobs” or “remote developer positions,” Google displays a dedicated job panel with filtering by location, company, date posted, and more.
JobPosting schema tells Google your page contains a job listing and provides the structured data needed for this aggregation. Without it, Google might understand your page discusses jobs but cannot extract the specific details needed for the jobs panel.
The difference matters significantly for recruitment:
| Listing Type | Google for Jobs Visibility | Typical Competition |
|---|---|---|
| With JobPosting schema | Eligible for jobs panel | Company-branded listing |
| Without schema | Standard organic only | Competing against Indeed, LinkedIn, ZipRecruiter |
Companies in competitive hiring markets, including Nashville-based employers facing tight labor pools, use JobPosting schema to appear alongside major job boards without paying aggregator fees.
Schema markup also enables apply buttons that link directly to your application page, bypassing third-party platforms that often add friction to the candidate experience.
Required Properties: Minimum Viable Job Listing
Four properties must appear in every JobPosting schema for Google to consider the listing valid. Missing any triggers validation errors and excludes the listing from Google for Jobs entirely.
title specifies the job title. Use the actual position title candidates search for, not internal job codes or creative titles. “Senior Software Engineer” works; “Code Ninja Level 3” does not.
description provides comprehensive information about the role. Google accepts HTML formatting here, so you can include paragraphs, lists, and headers. This field should cover responsibilities, requirements, benefits, and company information.
"description": "<p>We're looking for a Senior Software Engineer to join our platform team.</p><h3>Responsibilities</h3><ul><li>Design and implement scalable backend services</li><li>Mentor junior engineers</li></ul>"
datePosted indicates when the job was published in ISO 8601 format. Google uses this for recency filtering and to identify potentially stale listings.
"datePosted": "2025-01-15"
hiringOrganization identifies the employer using Organization schema nesting:
"hiringOrganization": {
"@type": "Organization",
"name": "Acme Corporation",
"sameAs": "https://www.acme.com",
"logo": "https://www.acme.com/logo.png"
}
Include the logo property when available. Job listings with company logos display more prominently in the jobs panel.
Location: Physical, Remote, and Hybrid Configurations
Job location handling has evolved significantly as remote work became standard. Google for Jobs supports multiple location configurations through the jobLocation and jobLocationType properties.
Physical location jobs require full address details:
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Main Street",
"addressLocality": "Nashville",
"addressRegion": "TN",
"postalCode": "37203",
"addressCountry": "US"
}
}
Fully remote positions use the TELECOMMUTE job location type:
"jobLocationType": "TELECOMMUTE"
For remote positions, you can optionally include applicantLocationRequirements to specify geographic eligibility:
"applicantLocationRequirements": {
"@type": "Country",
"name": "United States"
}
Hybrid arrangements combine physical location with remote eligibility:
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Nashville",
"addressRegion": "TN",
"addressCountry": "US"
}
},
"jobLocationType": "TELECOMMUTE"
This configuration indicates the job has a physical office but allows remote work. Candidates filtering for remote opportunities will find the listing.
| Work Type | jobLocation | jobLocationType |
|---|---|---|
| Fully on-site | Required with full address | Not included |
| Fully remote | Optional or omit | TELECOMMUTE |
| Hybrid | Required with office location | TELECOMMUTE |
Salary Information: Transparency That Improves Visibility
Salary transparency in job listings has shifted from optional to expected. Google for Jobs prominently displays salary information and allows candidates to filter by pay range. Listings with salary data receive preferential treatment in relevance ranking.
The baseSalary property uses MonetaryAmount schema:
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": {
"@type": "QuantitativeValue",
"value": 95000,
"unitText": "YEAR"
}
}
For salary ranges, use minValue and maxValue instead of a single value:
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": {
"@type": "QuantitativeValue",
"minValue": 85000,
"maxValue": 110000,
"unitText": "YEAR"
}
}
Supported unitText values include HOUR, DAY, WEEK, MONTH, and YEAR. Choose the unit that matches how you discuss compensation with candidates.
Salary transparency laws in many states now require pay ranges in job postings. Schema markup helps ensure this required information displays prominently to candidates regardless of the platform where they discover your listing.
Employment Type Classification
The employmentType property categorizes positions by work arrangement. Google supports multiple values in an array format:
"employmentType": ["FULL_TIME", "CONTRACTOR"]
Supported employment types:
| Type | Use Case |
|---|---|
| FULL<em>TIME | Standard permanent positions |
| PART</em>TIME | Reduced hours positions |
| CONTRACTOR | Independent contractor roles |
| TEMPORARY | Fixed-term positions |
| INTERN | Internship programs |
| VOLUNTEER | Unpaid positions |
| PER_DIEM | Day-rate arrangements |
| OTHER | Positions not fitting standard categories |
Accurate employment type classification helps candidates filter to relevant opportunities. A developer seeking full-time work wastes time on contract listings; proper tagging prevents this mismatch.
Handling Job Expiration
Expired job listings with active schema markup damage your site’s structured data quality score. Google expects job listings to remain current, and outdated postings signal poor maintenance.
The validThrough property specifies when the listing expires:
"validThrough": "2025-03-15T23:59:59Z"
When a position closes:
- Remove the JobPosting schema entirely, or
- Remove the page from your site with appropriate redirect handling
Do not leave expired listings with schema markup accessible. Google may continue crawling these pages, finding invalid structured data that impacts future listings.
For rolling job postings that remain open indefinitely, omit validThrough rather than setting arbitrary future dates. Update datePosted periodically if the position remains open to signal active recruitment.
Many applicant tracking systems automatically remove schema markup when positions close. If your ATS lacks this feature, build manual processes to audit active job schema against actual open positions.
Application Process Configuration
The directApply property indicates whether candidates can apply directly on your site:
"directApply": true
This property improves conversion by signaling candidates won’t face external redirects. Listings with direct apply capability often receive click preference from candidates tired of aggregator friction.
The applicationContact property provides recruiter information:
"applicationContact": {
"@type": "ContactPoint",
"telephone": "+1-615-555-0100",
"email": "careers@acme.com",
"contactType": "Human Resources"
}
While optional, application contact information builds trust and provides alternative paths for candidates who prefer direct outreach over form submissions.
Identifier and Additional Properties
Job identifiers help track positions across platforms:
"identifier": {
"@type": "PropertyValue",
"name": "Acme Corporation",
"value": "JOB-2025-001234"
}
The qualifications property lists required skills and experience:
"qualifications": "Bachelor's degree in Computer Science or equivalent experience. 5+ years of professional software development experience. Proficiency with Python, JavaScript, and SQL."
The responsibilities property details job duties:
"responsibilities": "Design and implement scalable backend services. Collaborate with product teams on feature development. Participate in code reviews and mentor junior developers."
These fields enhance the job description and may influence how Google matches queries to your listing.
Industry and Experience Requirements
The industry property categorizes the job’s sector:
"industry": "Technology"
Experience requirements specify years or levels needed:
"experienceRequirements": "5+ years of professional experience in software development"
For education requirements:
"educationRequirements": {
"@type": "EducationalOccupationalCredential",
"credentialCategory": "bachelor degree"
}
Google uses these fields for filtering and relevance matching. A candidate searching for “entry level marketing jobs” receives different results than one searching for “senior marketing director positions” based on experience requirement data.
Common Implementation Mistakes
Leaving expired jobs with active schema ranks as the most damaging mistake. This signals poor data quality to Google and may impact future listings’ rich result eligibility.
Missing hiringOrganization causes validation failure. Every job listing needs employer identification, even for staffing agencies posting on behalf of clients.
Wrong location format for remote jobs confuses Google’s classification. Use jobLocationType: “TELECOMMUTE” for remote eligibility rather than text like “Remote” in the location address.
Single job pages with multiple positions violate structured data guidelines. Each JobPosting schema should describe exactly one position. For multiple openings, create separate pages or use separate schema blocks with unique identifiers.
Missing salary when legally required may not trigger validation errors but could create compliance issues in jurisdictions with pay transparency laws.
| Mistake | Impact | Prevention |
|---|---|---|
| Expired jobs with schema | Quality score damage | Automated schema removal on close |
| No hiringOrganization | Validation failure | Template enforcement |
| Wrong remote configuration | Missed remote searches | Use jobLocationType properly |
| Multiple jobs per schema | Guidelines violation | One position per schema |
Validation and Monitoring
Google’s Rich Results Test validates JobPosting schema before publishing. Test individual job pages to identify errors and warnings.
Search Console’s job posting enhancement report shows:
- Total valid job listings on your site
- Listings with warnings that may still display
- Listings with errors excluded from Google for Jobs
- Specific error types affecting your listings
Monitor this report weekly during active recruiting. A sudden drop in valid listings may indicate ATS configuration changes or template issues affecting schema output.
For sites with many job listings, automate validation testing as part of your publishing workflow. Catch schema errors before Google does.
Complete JobPosting Schema Example
A fully-implemented job listing incorporates all discussed elements:
{
"@context": "https://schema.org/",
"@type": "JobPosting",
"title": "Senior Software Engineer",
"description": "<p>We're seeking a Senior Software Engineer to join our growing platform team.</p><h3>What You'll Do</h3><ul><li>Design and implement scalable backend services</li><li>Lead technical design discussions</li><li>Mentor junior engineers</li></ul><h3>What We Offer</h3><ul><li>Competitive salary and equity</li><li>Flexible remote work policy</li><li>Comprehensive health benefits</li></ul>",
"identifier": {
"@type": "PropertyValue",
"name": "Acme Corporation",
"value": "ENG-2025-0042"
},
"datePosted": "2025-01-15",
"validThrough": "2025-03-15T23:59:59Z",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "Acme Corporation",
"sameAs": "https://www.acme.com",
"logo": "https://www.acme.com/logo.png"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Nashville",
"addressRegion": "TN",
"addressCountry": "US"
}
},
"jobLocationType": "TELECOMMUTE",
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": {
"@type": "QuantitativeValue",
"minValue": 130000,
"maxValue": 170000,
"unitText": "YEAR"
}
},
"qualifications": "5+ years of software development experience. Proficiency with distributed systems and cloud infrastructure.",
"directApply": true
}
Adapt this structure to your positions while maintaining all required properties and keeping expiration dates current.
Sources
- Google Search Central: Job Posting Structured Data Documentation, https://developers.google.com/search/docs/appearance/structured-data/job-posting
- Schema.org: JobPosting Type Specification, https://schema.org/JobPosting
- Google Search Central: Structured Data General Guidelines, https://developers.google.com/search/docs/appearance/structured-data/sd-policies
JobPosting schema requirements evolve with labor market changes. Verify current specifications against Google’s documentation when implementing for production use.