Appearance
Google for Jobs & SEO
Google for Jobs surfaces job listings directly in Google search results with rich cards showing salary, location, and an "Apply" button. The Recruitly WordPress plugin stores all the structured data you need — this guide shows you how to output it as JSON-LD so Google picks it up.
How It Works
Google looks for JobPosting structured data (JSON-LD format) on each job page. When it finds valid data, your listing appears in the Google for Jobs widget — a dedicated panel at the top of search results for job-related queries.
Your WordPress job page → JSON-LD markup → Google crawls → Google for Jobs widgetSetup
Step 1 — Add the JSON-LD Snippet
Add this code to your theme's functions.php file. It generates structured data for each job post using the metadata synced by the Recruitly plugin.
php
function recruitly_google_jobs_schema() {
if (!is_singular('job')) return;
$post_id = get_the_ID();
// ── Configure these for your agency ──
$agency_name = 'Your Agency Name';
$currency = 'GBP'; // GBP, USD, EUR, AUD, etc.
$default_country = 'GB'; // 2-letter ISO country code
// Employment type mapping: Recruitly type → Google type
$type_map = [
'Permanent' => 'FULL_TIME',
'Contract' => 'CONTRACTOR',
'Temporary' => 'TEMPORARY',
'Part-Time' => 'PART_TIME',
'Internship' => 'INTERN',
'Volunteer' => 'VOLUNTEER',
'Per Diem' => 'PER_DIEM',
];
// ── Pull job metadata ──
$title = get_post_meta($post_id, 'webAdvertTitle', true) ?: get_the_title();
$description = get_post_meta($post_id, 'mainResponsibilities', true) ?: get_the_excerpt();
$job_type = get_post_meta($post_id, 'jobType', true);
$date_posted = get_post_meta($post_id, 'datePosted', true);
$closing = get_post_meta($post_id, 'closingDate', true);
$salary_from = get_post_meta($post_id, 'salaryFrom', true);
$salary_to = get_post_meta($post_id, 'salaryTo', true);
$salary_per = get_post_meta($post_id, 'salaryPer', true);
$city = get_post_meta($post_id, 'city', true);
$county = get_post_meta($post_id, 'county', true);
$country = get_post_meta($post_id, 'country', true);
$postcode = get_post_meta($post_id, 'postcode', true);
$is_remote = get_post_meta($post_id, 'isRemote', true);
// Unit mapping for salary period
$unit_map = [
'annum' => 'YEAR',
'day' => 'DAY',
'hour' => 'HOUR',
'month' => 'MONTH',
'week' => 'WEEK',
];
$schema = [
'@context' => 'https://schema.org/',
'@type' => 'JobPosting',
'title' => $title,
'description' => $description,
'datePosted' => $date_posted,
'hiringOrganization' => [
'@type' => 'Organization',
'name' => $agency_name,
],
'jobLocation' => [
'@type' => 'Place',
'address' => [
'@type' => 'PostalAddress',
'addressLocality' => $city,
'addressRegion' => $county,
'addressCountry' => $country ?: $default_country,
'postalCode' => $postcode,
],
],
];
if ($closing) {
$schema['validThrough'] = $closing;
}
if ($job_type && isset($type_map[$job_type])) {
$schema['employmentType'] = $type_map[$job_type];
}
if ($salary_from || $salary_to) {
$schema['baseSalary'] = [
'@type' => 'MonetaryAmount',
'currency' => $currency,
'value' => [
'@type' => 'QuantitativeValue',
'minValue' => $salary_from,
'maxValue' => $salary_to,
'unitText' => isset($unit_map[$salary_per]) ? $unit_map[$salary_per] : 'YEAR',
],
];
}
if ($is_remote) {
$schema['jobLocationType'] = 'TELECOMMUTE';
}
echo '<script type="application/ld+json">' . json_encode($schema, JSON_UNESCAPED_SLASHES) . '</script>';
}
add_action('wp_head', 'recruitly_google_jobs_schema');Step 2 — Configure Your Values
Update these variables at the top of the snippet:
| Variable | Description | Example |
|---|---|---|
$agency_name | Your company/agency name | 'Acme Recruitment' |
$currency | ISO currency code | 'GBP', 'USD', 'EUR', 'AUD' |
$default_country | Fallback ISO country code | 'GB', 'US', 'AU' |
$type_map | Map your Recruitly job types to Google's employment types | See code above |
Google accepts these employment types: FULL_TIME, PART_TIME, CONTRACTOR, TEMPORARY, INTERN, VOLUNTEER, PER_DIEM, OTHER.
Step 3 — Test Your Markup
Use Google's Rich Results Test to validate your job pages:
- Enter a job page URL
- Check that the
JobPostingstructured data is detected - Fix any warnings (missing salary data is a warning, not an error)
Step 4 — Submit Your Sitemap
- Go to Google Search Console
- Add your site if not already registered
- Submit your XML sitemap (usually
yoursite.com/sitemap.xml) - Google will begin crawling your job pages within 3–7 days
Best Practices
- Remove expired jobs — Google penalizes sites that show expired listings. Recruitly handles this automatically when you close a job in the CRM.
- Include salary ranges — listings with salary data get ~30% more clicks in Google for Jobs.
- Use standard job titles — "Senior Software Engineer" ranks better than "Code Ninja Level 3".
- Complete location data — include city, region, country, and postcode for best geo-matching.
- Mobile optimization — ensure your job pages are mobile-friendly, as most job searches happen on mobile.
Troubleshooting
Jobs not appearing in Google for Jobs?
- Verify the JSON-LD is rendering correctly (View Source → search for
application/ld+json) - Check the Rich Results Test for errors
- Ensure your sitemap is submitted and pages are indexed
- Allow 3–7 days after submission for Google to crawl
- Confirm that closed/expired jobs are actually removed from your site