Custom Post Type (Beta)
For sites that want jobs to live as native WordPress posts, the plugin can create a job_post custom post type.
This gives you full access to WordPress queries, templates, REST API, and plugin integrations for your job data.
How It Works
Section titled “How It Works”When enabled, the plugin registers a custom post type called job_post. A cron endpoint syncs jobs from the RecMan API into WordPress posts. Each sync cycle:
- Fetches all active jobs from the RecMan API
- Creates new WordPress posts for jobs not yet in the database
- Updates existing posts if the RecMan
updatedtimestamp is newer - Re-publishes posts that were previously marked as private (e.g. a job was temporarily removed and then re-added)
- Marks as private any published posts whose API ID no longer appears in the feed (expired/removed jobs are never deleted)
Each post stores the RecMan API job ID in the job_post_id meta field and a last_updated timestamp to avoid unnecessary updates.
Post Type Details
Section titled “Post Type Details”| Property | Value |
|---|---|
| Post type slug | job_post |
| URL slug (rewrite) | /jobs/ — e.g. yoursite.com/jobs/job-title/ |
| Archive URL | yoursite.com/jobs/ |
| Public | Yes |
| Show in REST | Yes (available via /wp-json/wp/v2/job_post) |
| Gutenberg | Yes |
| Supports | title, editor, author, thumbnail, excerpt, comments, custom-fields |
How to Enable
Section titled “How to Enable”- Go to RecMan Jobs > Settings in your WordPress admin
- Enable Custom Post Type
- Set up a cron job to trigger the sync URL (provided in the settings)
Sync Mechanism
Section titled “Sync Mechanism”The Custom Post Type sync is triggered via a secret cron URL:
https://yoursite.com/bonsy-recman-cron/{secret-key}The secret key is generated automatically when the plugin is activated and can be found (and regenerated) in the plugin settings. Set up a server cron or external service (like EasyCron or cron-job.org) to hit this URL on a regular schedule.
The endpoint returns a JSON response with a log of actions taken (created, updated, expired, skipped).
Custom Fields Reference
Section titled “Custom Fields Reference”Every synced job post stores its data as WordPress post meta. You can access these fields with get_post_meta() in your templates.
Core Fields
Section titled “Core Fields”| Meta Key | Description | Example Value |
|---|---|---|
job_post_id | RecMan API job ID (internal) | 12345 |
last_updated | Unix timestamp of last sync | 1710000000 |
name | Job name | Senior Developer |
title | Job title | Senior Developer |
companyName | Company name | Acme Corp |
workplace | Workplace name | Oslo Office |
Dates & Deadlines
Section titled “Dates & Deadlines”| Meta Key | Description |
|---|---|
startDate | Job start date |
endDate | Job end date |
deadline | Application deadline |
created | When the job was created in RecMan |
updated | When the job was last updated |
Job Details
Section titled “Job Details”| Meta Key | Description |
|---|---|
numberOfPositions | Number of open positions |
accession | Accession/entry information |
salary | Salary information |
sector | Job sector |
type | Employment type |
position | Position level |
positionType | Position type |
branchCategory | Primary branch category |
branch | Primary branch |
secondaryBranchCategory | Secondary branch category |
secondaryBranch | Secondary branch |
Location
Section titled “Location”| Meta Key | Description |
|---|---|
address1 | Street address line 1 |
address2 | Street address line 2 |
postalCode | Postal/ZIP code |
city | City |
country | Country |
location_city | Mapped location city |
location_country | Mapped location country |
location_region | Mapped location region |
locations | Structured location data (array) |
Organization
Section titled “Organization”| Meta Key | Description |
|---|---|
departmentId | RecMan department ID |
corporationId | RecMan corporation ID |
department | Department name |
corporation | Corporation name |
Media & Links
Section titled “Media & Links”| Meta Key | Description |
|---|---|
logo | Logo URL |
videoUrl | Video URL |
url | Job post URL on RecMan |
apply | Application URL |
website | Company website |
facebook | Facebook URL |
linkedIn | LinkedIn URL |
twitter | Twitter URL |
images | Image data (array) |
Social Sharing / SEO
Section titled “Social Sharing / SEO”| Meta Key | Description |
|---|---|
some_title | Social media title |
some_description | Social media description |
some_image | Social media image URL |
some_image_full | Full-size social media image URL |
Related Data
Section titled “Related Data”| Meta Key | Description |
|---|---|
companyDescription | Company description text |
contacts | Contact persons (array) |
skills | Required skills (array) |
similarJobs | Related/similar jobs (array) |
isExpired | Whether the job is expired |
Querying Job Posts
Section titled “Querying Job Posts”Basic Query
Section titled “Basic Query”$jobs = new WP_Query([ 'post_type' => 'job_post', 'posts_per_page' => 10, 'post_status' => 'publish',]);
while ($jobs->have_posts()) { $jobs->the_post(); $company = get_post_meta(get_the_ID(), 'companyName', true); $deadline = get_post_meta(get_the_ID(), 'deadline', true); $city = get_post_meta(get_the_ID(), 'city', true);
// Render your template...}wp_reset_postdata();Filter by Location
Section titled “Filter by Location”$jobs = new WP_Query([ 'post_type' => 'job_post', 'posts_per_page' => -1, 'meta_query' => [ [ 'key' => 'city', 'value' => 'Oslo', 'compare' => '=', ], ],]);Filter by Department
Section titled “Filter by Department”$jobs = new WP_Query([ 'post_type' => 'job_post', 'posts_per_page' => -1, 'meta_query' => [ [ 'key' => 'departmentId', 'value' => '42', 'compare' => '=', ], ],]);REST API
Section titled “REST API”Since show_in_rest is enabled, job posts are available at:
GET /wp-json/wp/v2/job_postGET /wp-json/wp/v2/job_post/{id}Custom meta fields are not exposed in the REST API by default. To expose specific fields, register them with show_in_rest:
add_action('init', function () { register_post_meta('job_post', 'companyName', [ 'show_in_rest' => true, 'single' => true, 'type' => 'string', ]);
register_post_meta('job_post', 'deadline', [ 'show_in_rest' => true, 'single' => true, 'type' => 'string', ]);
// Add more fields as needed...});Template Files
Section titled “Template Files”WordPress looks for template files in this order for single job posts:
single-job_post.php(in your theme)single.phpsingular.phpindex.php
And for the archive:
archive-job_post.php(in your theme)archive.phpindex.php
Create single-job_post.php in your theme to build a custom job detail page:
<?php get_header(); ?>
<?php while (have_posts()) : the_post(); ?> <article class="job-post"> <h1><?php the_title(); ?></h1>
<?php if ($company = get_post_meta(get_the_ID(), 'companyName', true)) : ?> <p class="job-company"><?= esc_html($company) ?></p> <?php endif; ?>
<?php if ($deadline = get_post_meta(get_the_ID(), 'deadline', true)) : ?> <p class="job-deadline">Deadline: <?= esc_html($deadline) ?></p> <?php endif; ?>
<div class="job-content"> <?php the_content(); ?> </div>
<?php if ($apply_url = get_post_meta(get_the_ID(), 'apply', true)) : ?> <a href="<?= esc_url($apply_url) ?>" class="btn">Apply Now</a> <?php endif; ?>
<?php $contacts = get_post_meta(get_the_ID(), 'contacts', true); if (is_array($contacts) && !empty($contacts)) : ?> <h2>Contact</h2> <ul> <?php foreach ($contacts as $contact) : ?> <li><?= esc_html($contact['name'] ?? '') ?> — <?= esc_html($contact['email'] ?? '') ?></li> <?php endforeach; ?> </ul> <?php endif; ?> </article><?php endwhile; ?>
<?php get_footer(); ?>Limitations
Section titled “Limitations”When to Use This
Section titled “When to Use This”The Custom Post Type is useful when you need:
- Jobs to appear in WordPress search results
- Jobs in sitemaps generated by SEO plugins (Yoast, Rank Math, etc.)
- Integration with other WordPress plugins that work with custom post types (Elementor, ACF, FacetWP, etc.)
- REST API access to job data
- Full control over templating with theme template files
For most use cases, the standard caching + shortcode/template approach is simpler and recommended.