Skip to Content

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:

  1. Detect job pages: The crawler identifies pages with:

    • URL patterns (/careers/, /jobs/, /vacancies/, /hiring/)
    • Visible salary/employment type content
    • Job description and requirements
  2. Extract structured data: The crawler looks for JSON-LD, Microdata, or RDFa blocks on the page

  3. Check for JobPosting schema: The crawler verifies if any schema block has:

    • @type set to JobPosting
    • Required properties: title, description, datePosted, hiringOrganization, jobLocation
  4. Validate schema completeness: If JobPosting schema is found, the crawler checks for:

    • datePosted property (required by Google)
    • hiringOrganization property (required by Google)
    • jobLocation property (required by Google)
    • validThrough expiry date (recommended)
    • baseSalary with range (recommended)
    • employmentType declared (recommended)
  5. Trigger conditions: The issue is flagged when:

    • Job listing page doesn’t have JobPosting schema
    • JobPosting schema exists but datePosted is missing
    • JobPosting schema exists but hiringOrganization is missing
    • JobPosting schema exists but jobLocation is missing

How To Fix

  1. Identify job listing pages: Look for pages with:

    • URL patterns (/careers/, /jobs/, /vacancies/, /hiring/)
    • Visible salary/employment type content
    • Job description and requirements
  2. 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" } } }
  3. Include required properties:

    • title: Job title
    • description: Job description (can include HTML)
    • datePosted: ISO 8601 date format
    • hiringOrganization: Organization hiring for the role
    • jobLocation: Place or remote flag
  4. Add recommended properties:

    • validThrough: Job posting expiry date
    • baseSalary: Salary range (use MonetaryAmount)
    • employmentType: FULL_TIME, PART_TIME, CONTRACTOR, TEMPORARY, INTERN, VOLUNTEER
    • jobLocationType: “TELECOMMUTE” for remote roles
  5. 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

FieldTypeDescription
schemaTypeSchemaTypeThe type of schema (e.g., Organization, Person)
schemaFormatSchemaFormatThe format of the schema (JSON-LD, Microdata, RDFa)
schemaIdentifierString?Unique identifier for the schema
rawJsonJson?The raw JSON-LD or structured data content
schemaErrorsJson?Array of validation errors found in the schema
isValidSchemaBoolean?Whether the schema is valid according to validation
missingFieldsJson?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 JobPosting schema with title, description, datePosted, and hiringOrganization — 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
  • xeopix-crawling-v2/toggleGroups/structuredDataRichResults.js
  • xeopix-crawling-v2/issueCodes.js
  • xeopix-crawling-v2/utils/context.js
  • xeopix-crawling-v2/utils/issues.js
  • xeopix-crawling-v2/utils/schema.js

Coverage Summary

  • Covers valid JobPosting schema detection
  • Covers empty HTML resilience

References

Last updated on