No JobPosting schema on a careers page
What Is This Issue
Job listing pages are missing JobPosting schema, preventing the role from appearing in Google for Jobs — the highest-intent job search placement available in SERPs.
Without JobPosting schema:
- Your job listings won’t appear in Google for Jobs
- Job details (salary, employer, location, posting date) won’t show in search
- Job seekers can’t find your openings through Google’s job search
- You’ll miss out on high-intent job applicants
- Rich snippets for jobs won’t display
A proper JobPosting schema should include: @type (JobPosting), title, description, datePosted, hiringOrganization, jobLocation, and optionally validThrough, baseSalary, employmentType, jobLocationType.
Why Is This Important
JobPosting schema is critical for recruitment and job visibility:
- Google for Jobs: Enables job listings to appear in Google’s dedicated job search interface
- Rich results: Shows salary, employer, location, and posting date in search results
- High-intent applicants: Job seekers using Google for Jobs are actively looking for work
- Visibility: Increases job listing visibility beyond traditional job boards
- AI search readiness: AI engines use JobPosting schema to answer job-related queries
- Application rates: Jobs with proper schema get more qualified applicants
Resolving this issue improves your SEO health score by ensuring job listings are properly structured for maximum visibility and applicant reach.
How XeoPix Detects This
XeoPix follows these logical steps to detect missing JobPosting schema:
-
Detect job pages: The crawler identifies pages with:
- URL patterns (
/careers/,/jobs/,/vacancies/,/hiring/) - Visible salary/employment type content
- Job description and requirements
- URL patterns (
-
Extract structured data: The crawler looks for JSON-LD, Microdata, or RDFa blocks on the page
-
Check for JobPosting schema: The crawler verifies if any schema block has:
@typeset toJobPosting- Required properties:
title,description,datePosted,hiringOrganization,jobLocation
-
Validate schema completeness: If JobPosting schema is found, the crawler checks for:
datePostedproperty (required by Google)hiringOrganizationproperty (required by Google)jobLocationproperty (required by Google)validThroughexpiry date (recommended)baseSalarywith range (recommended)employmentTypedeclared (recommended)
-
Trigger conditions: The issue is flagged when:
- Job listing page doesn’t have JobPosting schema
- JobPosting schema exists but
datePostedis missing - JobPosting schema exists but
hiringOrganizationis missing - JobPosting schema exists but
jobLocationis missing
How To Fix
-
Identify job listing pages: Look for pages with:
- URL patterns (
/careers/,/jobs/,/vacancies/,/hiring/) - Visible salary/employment type content
- Job description and requirements
- URL patterns (
-
Add JobPosting JSON-LD structured data to the page’s
<head>or before</body>:{ "@context": "https://schema.org", "@type": "JobPosting", "title": "Senior Frontend Developer", "description": "We need a React developer with 5+ years of experience...", "datePosted": "2024-03-01", "validThrough": "2024-05-01", "employmentType": "FULL_TIME", "hiringOrganization": { "@type": "Organization", "name": "Example Corp", "sameAs": "https://example.com" }, "jobLocation": { "@type": "Place", "address": { "@type": "PostalAddress", "addressLocality": "Austin", "addressRegion": "TX", "addressCountry": "US" } }, "baseSalary": { "@type": "MonetaryAmount", "currency": "USD", "value": { "@type": "QuantitativeValue", "minValue": "120000", "maxValue": "160000", "unitText": "YEAR" } } } -
Include required properties:
title: Job titledescription: Job description (can include HTML)datePosted: ISO 8601 date formathiringOrganization: Organization hiring for the rolejobLocation: Place or remote flag
-
Add recommended properties:
validThrough: Job posting expiry datebaseSalary: Salary range (use MonetaryAmount)employmentType: FULL_TIME, PART_TIME, CONTRACTOR, TEMPORARY, INTERN, VOLUNTEERjobLocationType: “TELECOMMUTE” for remote roles
-
Validate with Google’s Rich Results Test
What We Store
Storage Level
Page Level — This issue is evaluated for each individual URL that contains structured data.
Database Table / Prisma Model
PageStructuredData
Stored Fields
| Field | Type | Description |
|---|---|---|
| schemaType | SchemaType | The type of schema (e.g., Organization, Person) |
| schemaFormat | SchemaFormat | The format of the schema (JSON-LD, Microdata, RDFa) |
| schemaIdentifier | String? | Unique identifier for the schema |
| rawJson | Json? | The raw JSON-LD or structured data content |
| schemaErrors | Json? | Array of validation errors found in the schema |
| isValidSchema | Boolean? | Whether the schema is valid according to validation |
| missingFields | Json? | Array of required fields that are missing |
Detection Dependencies
- The following data sources are required to evaluate this issue:
- HTML Document — The crawler parses the HTML to find structured data (JSON-LD, Microdata, RDFa)
- Structured Data Validation — The extracted schema is validated against Schema.org definitions
- Schema Parser — JSON-LD scripts, Microdata attributes, and RDFa markup are parsed
Examples
Example 1: Missing JobPosting Schema on Job Listing
Problematic state:
<!-- Job listing page without JobPosting schema -->
<html>
<head>
<title>Senior Frontend Developer - Example Corp</title>
</head>
<body>
<h1>Senior Frontend Developer</h1>
<p>We need a React developer with 5+ years of experience...</p>
<p><strong>Location:</strong> Austin, TX</p>
<p><strong>Type:</strong> Full Time</p>
<p><strong>Salary:</strong> $120,000 - $160,000</p>
</body>
</html>Corrected state:
<!-- Job listing page with JobPosting schema -->
<html>
<head>
<title>Senior Frontend Developer - Example Corp</title>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Senior Frontend Developer",
"description": "We need a React developer with 5+ years of experience...",
"datePosted": "2024-03-01",
"validThrough": "2024-05-01",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "Example Corp",
"sameAs": "https://example.com"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Austin",
"addressRegion": "TX",
"addressCountry": "US"
}
},
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "USD",
"value": {
"@type": "QuantitativeValue",
"minValue": "120000",
"maxValue": "160000",
"unitText": "YEAR"
}
}
}
</script>
</head>
<body>
<h1>Senior Frontend Developer</h1>
<p>We need a React developer with 5+ years of experience...</p>
<p><strong>Location:</strong> Austin, TX</p>
<p><strong>Type:</strong> Full Time</p>
<p><strong>Salary:</strong> $120,000 - $160,000</p>
</body>
</html>Example 2: Remote Job with JobPosting Schema
Corrected state for remote position:
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Remote SEO Specialist",
"description": "Work from anywhere as an SEO specialist...",
"datePosted": "2024-03-15",
"employmentType": "FULL_TIME",
"jobLocationType": "TELECOMMUTE",
"hiringOrganization": {
"@type": "Organization",
"name": "Example Corp"
}
}Example 3: Incomplete JobPosting Schema
Problematic state:
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Marketing Manager"
}Missing required properties: description, datePosted, hiringOrganization, jobLocation
Corrected state:
{
"@context": "https://schema.org",
"@type": "JobPosting",
"title": "Marketing Manager",
"description": "Lead our marketing team and develop strategies...",
"datePosted": "2024-03-10",
"hiringOrganization": {
"@type": "Organization",
"name": "Example Corp"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "New York",
"addressRegion": "NY",
"addressCountry": "US"
}
}
}Unit Test
Test File
xeopix-crawling-v2/__tests__/seo-audit-checks/structuredDataRichResults/issue-152-jobposting-schema.test.js
Purpose
Validates that the crawler correctly validates JobPosting JSON-LD schemas and does not report false positives when the schema is properly formed.
Tested Function
runStructuredDataRichResults()
Issue Information
- Issue Number: 152
- Issue Code:
jobposting_schema_careers - Toggle Group:
structuredDataRichResults
Test Scenarios
Positive Test Cases
- Valid JobPosting schema: Page has a
JobPostingschema withtitle,description,datePosted, andhiringOrganization— no issue reported.
Negative Test Cases
None — the test only validates that valid schemas pass.
Boundary Cases
None.
Edge Cases
- Empty HTML:
<html></html>— no crash.
Expected Outcome
Pass
Issue should not be reported when a valid JobPosting schema with required properties is present.
Fail
No negative test cases are defined.
Validation
- Correct pass-through of valid JobPosting schemas
- Graceful handling of empty HTML
Related Production Files
xeopix-crawling-v2/toggleGroups/structuredDataRichResults.jsxeopix-crawling-v2/issueCodes.jsxeopix-crawling-v2/utils/context.jsxeopix-crawling-v2/utils/issues.jsxeopix-crawling-v2/utils/schema.js
Coverage Summary
- Covers valid JobPosting schema detection
- Covers empty HTML resilience
References
- Schema.org — JobPosting — Schema.org
- Google — Job Posting Structured Data — Google Search Central