Getting listings into Google for Jobs is the main reason most people install this plugin, and that placement depends entirely on the structured data on each job page. If the JSON-LD is wrong or incomplete the listing is skipped, usually with no visible sign on your site that anything is broken. This page shows what the plugin outputs, which settings control it, how to validate it, and how to read the errors Google reports back.
To be clear up front: correct structured data makes a job eligible for Google for Jobs. It does not guarantee inclusion. Google decides what to show.
What the plugin outputs on a job page
On every single job page the plugin prints its own metadata into <head>, wrapped in an HTML comment reading Metadata Generate with Loxo plugin so you can find it in View Source. It contains three things.
- Search engine tags — a
<title>of “Job Title | Site Name”, a meta description built as “Hiring [Job Title] – [Type]. Job location [City]. Compensation [Salary].” (the salary sentence is dropped when salary is hidden), a canonical link to the job permalink, and robots directives fixed atindex, follow, withmax-snippet:-1andmax-image-preview:largefor Googlebot and Bingbot. - Open Graph tags —
og:type,og:locale,og:title,og:description,og:url,og:site_nameandarticle:published_time, plusarticle:modified_timewhen the job has an update date. There is noog:image, so a shared job link carries no preview image. - A JSON-LD JobPosting block — the part Google for Jobs reads.
The JobPosting schema, in full
Below is the complete JSON-LD the plugin generates for an on-site job with a salary range. It is printed on one line in the page source, and formatted here for readability. Compare it against your own output to spot a missing or empty field.
{
"@context": "https://schema.org/",
"@type": "JobPosting",
"title": "Senior Backend Engineer",
"description": "Northwind Talent is hiring a Senior Backend Engineer to join the payments team. You will design and ship services, own them in production, and work alongside product and design. We are looking for someone with five years of experience in a similar role who enjoys",
"identifier": {
"@type": "PropertyValue",
"name": "Northwind Talent",
"value": 3122253
},
"datePosted": "2026-07-14",
"validThrough": "2027-01-10",
"employmentType": "FULL_TIME",
"hiringOrganization": {
"@type": "Organization",
"name": "Northwind Talent",
"sameAs": "https://northwindtalent.com/",
"logo": "https://northwindtalent.com/logo.png"
},
"jobLocation": {
"@type": "Place",
"address": {
"@type": "PostalAddress",
"streetAddress": "18 Bishopsgate",
"addressLocality": "London",
"addressRegion": "England",
"postalCode": "EC2N 4AJ",
"addressCountry": "GB"
}
},
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "GBP",
"value": {
"@type": "QuantitativeValue",
"minValue": "70000.00",
"maxValue": "90000.00",
"value": "90000.00",
"unitText": "YEAR"
}
}
}
Five details explain most of what you will see in your own output:
descriptionis not your full job description. The plugin strips all HTML, collapses whitespace, then trims to the first 50 words — so the schema carries a summary, not the complete posting.identifier.valueis the Loxo job ID;identifier.namereuses your hiring company name.employmentTypecomes from the job type in Loxo, uppercased with spaces turned into underscores, so “Full Time” becomesFULL_TIME. “Contract” is special-cased toCONTRACTOR. A job with no type defaults toFULL_TIME.jobLocation.addressis always present, and any field the job has no value for is emitted as an empty string rather than omitted.- Salary amounts come from Loxo, formatted to two decimal places. A single figure rather than a range emits
valuealone, withoutminValue/maxValue.unitTextis the pay period uppercased —YEAR,MONTH,WEEK,DAY,HOURorOTHER.
For a job whose location type in Loxo is remote and which has a country code, two extra fields are added after jobLocation:
"jobLocationType": "TELECOMMUTE",
"applicantLocationRequirements": {
"@type": "Country",
"name": "US"
},
Both conditions must hold. A job marked remote with no country code gets neither field and is published as an ordinary on-site job with a mostly empty address — the most common reason remote listings are rejected. See Available Job Data for how each Loxo field maps into WordPress.
Which settings feed which schema fields
Most of the schema comes straight from the Loxo job record and cannot be edited in WordPress. These five settings are the parts you control, under Loxo Jobs → Settings (see Plugin Settings).
| Setting | Section | Schema field it controls |
|---|---|---|
| Hiring Company Name | Company Settings | hiringOrganization.name and identifier.name |
| Hiring Company Url | Company Settings | hiringOrganization.sameAs |
| Hiring Company Logo | Company Settings | hiringOrganization.logo |
| Default job validity (in days) | SEO Settings | validThrough, used only when the job has no expiry date from Loxo. Default 180 days from the publication date. |
| Hide Salary? | Template Settings | When ticked, baseSalary is removed from the schema entirely, and the salary sentence is dropped from the meta description. |
Note that Hide Salary? lives in Template Settings, not SEO Settings — it is easy to miss when you are hunting for why baseSalary has disappeared. For how validThrough is calculated in detail, see Job Expiration.
How to validate your output
Rich Results Test — one page, immediate
- Open search.google.com/test/rich-results and paste a published job URL.
- Choose the Googlebot smartphone crawler — that is what Google indexes with.
- Expand the “Job postings” result to see detected fields, errors and warnings.
- Use View tested page → HTML to confirm the JSON-LD Google actually received rather than what you expect to be there. This is how you catch a cache serving a stale page.
Test at least three jobs — one on-site with a salary, one remote, one with no salary. They exercise different branches of the schema and fail in different ways.
Search Console — the whole site, over time
- Open Enhancements → Job postings. The report only appears once Google has crawled and detected job pages, which can take days after launch.
- Invalid items are grouped by issue type; click one to see the affected URLs.
- Fix the cause, then use Validate fix. Revalidation takes up to about two weeks.
- To recheck a single URL immediately, paste it into URL Inspection and run the live test.
If you need Google to see changes quickly rather than waiting for a recrawl, enable the Google Indexing API, which pings Google directly whenever a job is created, updated or removed.
Common Search Console errors and how to fix them
Google treats title, description, datePosted, hiringOrganization and jobLocation as required — a problem there is an error and the listing is not eligible. validThrough, baseSalary, employmentType, identifier and the remote fields are recommended, so problems there are warnings and the listing can still appear.
Missing field “name” in hiringOrganization (error)
Hiring Company Name is empty. The field is blank on a new install and the plugin does not fall back to your site name, so out of the box every job page emits an empty company name — which is a required field, hence an error rather than a warning. Fill the field in under Company Settings and save.
Invalid URL in field “logo” or “sameAs” (warning)
Both come from Company Settings and both are blank on a new install, so an untouched site emits an empty logo and an empty sameAs. Hiring Company Logo fills logo and Hiring Company Url fills sameAs; the plugin does not substitute your home URL for the latter. Paste a full absolute URL into each — https://example.com/logo.png, not /wp-content/uploads/logo.png, and not a link to the media library attachment page.
The value provided for validThrough is in the past
The job has passed its expiry date but is still published. Google dropping it is correct — but if the role is still open, the date is wrong, not the job. If the job carries an expiry date from Loxo, fix it in Loxo and sync — Default job validity will not help here, as the plugin uses that setting only for jobs that have no Loxo expiry date at all. The alternative is the free Auto-Extend Expiry add-on, which rolls the date forward automatically; note that it ships switched off and does nothing until you enable it on its own admin page, and that once enabled it overrides the date coming from Loxo on every sync. Use one approach or the other, not both. The plugin does not add noindex to expired jobs — the page stays indexable, it just loses its Google for Jobs placement.
Missing or incomplete jobLocation, especially on remote roles
Because the address object is always emitted, a job with no location data produces a PostalAddress of empty strings and Google reports the missing pieces, typically addressCountry and addressLocality. The fix is in Loxo, not WordPress: set the country (and city where relevant) on the job record, then resync. For a remote role the country code is also what triggers jobLocationType: TELECOMMUTE, so a remote job without one keeps failing until it is set.
Missing field “baseSalary” (warning)
Three things suppress it. Hide Salary? removes it deliberately. Otherwise the plugin only emits baseSalary when the job has an amount and a currency and a pay period — a figure with no currency set in Loxo produces nothing. And a pay period Loxo classifies as other emits unitText: OTHER, which Google does not recognise; pick a real period on the Loxo record.
Invalid value in field “employmentType” (warning)
The value is generated mechanically from the job type name, so a custom type such as “Contract To Hire” becomes CONTRACT_TO_HIRE, which Google does not accept. Rename the type in Loxo to one that maps cleanly — Full Time, Part Time, Contract, Temporary, Intern or Volunteer.
Yoast, Rank Math and job pages
Worth stating plainly, because it surprises people: on single job pages the plugin removes Yoast SEO and Rank Math output entirely and prints its own. Your SEO plugin’s title template, meta description, canonical, Open Graph tags and schema graph are all suppressed there. This is deliberate — two plugins writing competing title tags and schema into one page is worse than one, and this plugin has job data the SEO plugin does not. If you edited a Yoast snippet for a job and it is “not working”, that is why: the edit is saved, it is simply not printed.
The suppression is scoped to single job pages only. Your job archive, category and city pages, and every other page on the site, are still handled by your SEO plugin as normal.
The jobs XML sitemap
Enable Enable Jobs Sitemap? under SEO Settings and the plugin serves a sitemap at /loxo-jobs-sitemap.xml, listing every published job with a <lastmod> taken from the post’s last modification time. It ships with a stylesheet, so it is readable in a browser rather than raw XML. The plugin also appends a Sitemap: line to your robots.txt.
Leave it off if something else already covers the job post type. Yoast and Rank Math both generate custom post type sitemaps by default, and WordPress core’s sitemap at /wp-sitemap.xml includes jobs too — the settings page tells you when core sitemaps are active. Duplicate sitemaps do no harm, but gain you nothing. Turn it on when you have no SEO plugin, or when you have deliberately excluded jobs from your SEO plugin’s sitemap.
It lists all published jobs regardless of expiry date — expiry affects validThrough in the schema, not whether a job appears on your site or in the sitemap.
Troubleshooting
No JSON-LD in the page source at all
Search the source for Metadata Generate with Loxo plugin. If that comment is missing, you are not on a single job page — a job rendered inside a shortcode on a normal page or through a page builder does not get the metadata block, because it is tied to the job post type’s own template. Check the URL is the job’s own permalink, and that the job is published rather than a draft.
Changes to company settings do not show up
The schema is built on each page load, so there is no schema cache to clear — but page caching, a CDN or object caching will happily keep serving the old <head>. Purge your cache and recheck with a cache-busting query string before concluding the setting did not save.
The schema description is cut off mid-sentence
Expected. The description is trimmed to 50 words. Your full description is still on the page for readers and for Google’s normal indexing; only the schema copy is shortened.
Accented or non-Latin characters are missing from the schema description
When the plugin cleans the description for the schema it replaces every non-ASCII character with a space. This is not occasional: accented Latin letters such as é, ü and ñ are always replaced, and so is every character in a non-Latin script.
For a site posting in Japanese, Arabic, Cyrillic, Greek, Thai or any other non-Latin script, that leaves the schema description empty — a required field, so the listing is not eligible for Google for Jobs. Sites posting in English see it as scattered gaps around accented names and place names instead.
It affects the schema copy only; the description shown on the job page is untouched and displays correctly. This is a plugin limitation rather than anything you can configure around — get in touch if it affects your listings.
The sitemap URL in robots.txt is not the one I expected
When Yoast SEO is active, the robots.txt entry and the “View Sitemap” button point at /loxo_job-sitemap.xml — Yoast’s own sitemap for the job post type — rather than /loxo-jobs-sitemap.xml. That is intended, so the two do not compete. The plugin’s own sitemap is still reachable at its own URL.
404 on the sitemap URL
The sitemap is served through a rewrite rule that only exists while the setting is on. Saving the settings page schedules a rewrite flush, which is applied on the next page load — so load any page on the site once after enabling it. If it still 404s, visit Settings → Permalinks and save to force a flush. A 404 with the rule in place means there are no published jobs to list.
FAQ
Does valid schema guarantee my jobs appear in Google for Jobs?
No. Valid structured data makes a posting eligible; Google chooses what to show and can decline for reasons that have nothing to do with your markup. Treat a clean Rich Results Test as the entry requirement, not the outcome.
My schema validates but the job still is not showing. Why?
Usually one of four things: the page has not been crawled yet, which routinely takes days to weeks on a new site; validThrough is in the past; the site or the job URL is blocked from crawling; or Google has indexed the job but has not surfaced it for the queries you are testing. Confirm indexing first with URL Inspection in Search Console, then look at the schema.
Should I keep filled roles published?
Google’s guidance is to remove a posting once the role closes, and a listing whose validThrough has passed leaves Google for Jobs on its own. Leaving filled roles up indefinitely with a rolling expiry date is the opposite of what Google asks for and risks the whole site’s job listings, not just one page. Close jobs in Loxo and let them sync out.
Related documentation
- Auto-Extend Expiry — keeps validThrough near-term automatically instead of expiring listings manually.
- Job Expiration — how the expiry date behind validThrough is set and calculated.
- Plugin Settings — the Company Settings, SEO Settings and Template Settings sections referenced above.
- Google Indexing API — notify Google immediately when a job changes, instead of waiting for a recrawl.
- Available Job Data — which Loxo fields are stored in WordPress and feed the schema.
- Synchronizing Jobs — pull corrected data from Loxo after fixing a job record.
