Wbcom Designs WP Career Board Docs
Back to product Buy Now

Getting Started

Install, set up, and configure WP Career Board.

Introduction to WP Career Board

WP Career Board is a complete job board plugin for WordPress built natively on the WordPress Interactivity API. It lets you launch a full-featured job marketplace on any WordPress site - no shortcodes, no page reloads, no jQuery.

WP Career Board - Job Board Overview

What You Get

For your site visitors:

  • A fast, reactive job board that updates without page reloads
  • Search and filter jobs by keyword, category, job type, location, and experience level
  • Bookmark jobs to apply later
  • Full job detail pages with company information

For employers:

  • Self-service job posting with a guided multi-step form
  • Employer dashboard to manage all posted jobs and applications
  • Company profile page visible to all candidates

For candidates:

  • Candidate dashboard to track all applications in one place
  • Saved jobs list (bookmarks)
  • Apply as any logged-in member - no dedicated Candidate role required (set "Require Candidate Role" in Settings if you want stricter separation)
  • Resume builder and resume management (with WP Career Board Pro)

For admins:

  • Full admin control over jobs, applications, employers, and candidates
  • Moderation queue to approve jobs before they go live
  • Email notification system for all key events
  • GDPR-compliant data export and erasure tools

Key Differences From Other Job Board Plugins

Feature WP Career Board Traditional plugins
Page reloads on filter/apply No Yes
Built on WordPress Interactivity API Yes No
BuddyX Pro + Reign first-class support Yes No
No shortcodes required Yes Rarely
PHP 8.1 + WP 6.9 native Yes No

Requirements

  • WordPress: 6.9 or higher
  • PHP: 8.1 or higher
  • Browser: Any modern browser (Chrome, Firefox, Safari, Edge)

Free vs Pro

WP Career Board is free and fully functional as a standalone job board. WP Career Board Pro extends it with:

  • Resume builder with structured sections
  • Custom field builder for jobs, companies, and candidates
  • Application pipeline with custom hiring stages on top of the built-in Kanban board
  • Credit system to sell job-posting credits to employers
  • Multi-board engine
  • Job alerts (saved searches sent by email)
  • AI job descriptions (auto-generate job posts with AI)
  • AI hiring tools: applicant ranking, fit-score and TL;DR summaries, candidate "Recommended for you" matches, and "Write with AI" cover letters (each requires an AI provider configured in Pro)
  • Job map (interactive map with geocoded pins)
  • Job feed (RSS/XML for aggregators)
  • Priority support from the Wbcom Designs team

Start free. You can install WP Career Board and run a complete job board at no cost. Upgrade to Pro when you need advanced features.

Installation

WP Career Board is distributed exclusively via wbcomdesigns.com. It is not available on WordPress.org.

Before You Begin

Make sure your site meets these requirements:

  • WordPress 6.9 or higher
  • PHP 8.1 or higher
  • A modern block theme or classic theme (Reign or BuddyX Pro recommended)

Install the Plugin

  1. Log in to your WordPress admin (/wp-admin)
  2. Go to Plugins → Add New → Upload Plugin
  3. Click Choose File and select the wp-career-board.zip file you downloaded from wbcomdesigns.com
  4. Click Install Now
  5. Click Activate Plugin

Plugin Upload Screen

After activation, you will see the Career Board menu item in your admin sidebar.

What Gets Created on Activation

When you activate the plugin for the first time, WP Career Board automatically:

  • Creates five custom post types: Jobs, Companies, Applications, Resumes, and Boards
  • Registers five job taxonomies: Category, Job Type, Location, Experience Level, and Tag
  • Creates three user roles: Employer, Candidate, and Job Moderator
  • Adds the Career Board top-level menu to wp-admin (with Jobs, Applications, Candidates, Companies, Employers, and Settings)
  • Launches the Setup Wizard to help you create your pages

After Activation

You will be redirected to the Setup Wizard. The wizard creates all required pages with the correct blocks in about 30 seconds. See Setup Wizard for the full walkthrough.

If you dismiss the wizard, you can run it again any time from Career Board → Settings → Run Setup Wizard (the button in the page header).

Updating the Plugin

  1. Download the latest version from your account at wbcomdesigns.com
  2. Go to Plugins → Add New → Upload Plugin
  3. Upload the new zip - WordPress will ask if you want to replace the current version
  4. Click Replace current with uploaded

Note: Your settings, jobs, applications, and user data are preserved on updates.

Setup Wizard

The Setup Wizard is the fastest way to get your job board up and running. It creates all the pages you need in two quick steps.

Setup Wizard - Welcome Screen

What the Wizard Does

Step 1 - Create Pages

The wizard creates six pages automatically, each with the correct block placed and configured:

Page Block(s) Purpose
Find Jobs Heading + Job Search + Job Filters + Job Listings Main job board browse page
Post a Job Job Form Multi-step form for employers to submit listings
Employer Registration Employer Registration Unified registration for both employers and candidates (users choose "Find a Job" or "Hire Talent")
Employer Dashboard Employer Dashboard Employer manages jobs + applications
Candidate Dashboard Candidate Dashboard Candidate tracks applications + saved jobs
Companies Company Archive Browsable company directory

Step 2 - Sample Data

Optionally install demo content - 3 companies, 8 published jobs across multiple categories, and all taxonomy terms. This lets you see how the board looks with real content before going live.

Safe to re-run. The wizard checks for existing pages first. If a page with the correct block already exists, it will not create a duplicate.

Extensible. WP Career Board Pro and other add-ons can append their own steps using the wcb_wizard_steps filter and their own pages using the wcb_wizard_required_pages filter.

Running the Wizard

  1. After plugin activation, the wizard launches automatically
  2. Click Create Pages & Continue - the wizard creates all pages and shows a progress indicator
  3. On Step 2, optionally click Install Sample Data to add demo content
  4. Click Finish Setup to complete

Setup Wizard - Pages Created

Running the Wizard Again

If you dismissed the wizard or need to reset your pages:

  1. Go to Career Board → Settings
  2. Click Run Setup Wizard in the header

After the Wizard

Once complete, your site has a working job board. Next steps:

Adding Blocks to Pages

WP Career Board uses WordPress blocks to display everything on the frontend. Each block handles a specific part of the job board experience.

Available Blocks

WP Career Board includes 17 blocks. Search the block inserter for "Career Board" or the block name to find them. (There is also a WP Career Board category in the pattern inserter for the bundled page patterns - Full Job Board, Post a Job Form, Employer Dashboard, Candidate Dashboard, and Company Directory.)

Block What It Does
Candidate Dashboard Tabbed candidate dashboard: Overview, My Applications, Saved Jobs, and Account Settings. My Resumes and Job Alerts tabs are added by Pro.
Company Archive Interactive company directory with grid/list toggle and industry/size filters.
Company Profile Public company profile with owner inline-edit and active job listings.
Employer Dashboard Tabbed employer dashboard with 6 tabs: Overview, My Jobs, Post a Job, Applications, Company Profile, and Settings. The Applications tab has a List / Board (Kanban) toggle - the Board groups applicants into Submitted, Reviewing, Shortlisted, Hired, and Rejected columns, and dragging a card changes the applicant's status.
Employer Registration Unified registration form for both employers and candidates. Users choose "Find a Job" (candidate) or "Hire Talent" (employer) on the same form.
Featured Jobs Static server-rendered grid of featured (flagged) jobs. Good for homepages.
Job Alerts CTA A call-to-action card prompting candidates to create a job alert. The alert creation itself is a Pro feature.
Job Filters Taxonomy filter dropdowns (category, type, location, experience) for the job listings grid.
Job Form Multi-step (4-step) wizard for employers to post new jobs. Best for the full Post-a-Job experience.
Job Form (Single-Page) Every field on one screen - sidebar, modal, partner page, single-page-site alternative to the wizard. Submits to the same endpoint and honours the same field-builder filters. Posting only; editing routes through the wizard.
Job Listings Reactive job listings grid with load-more and bookmark toggle. Updates on search/filter without page reload.
Job Search Keyword search bar that drives the job listings grid.
Job Search Hero Full-width search form with optional category, location, and job type filter dropdowns. Horizontal or vertical layout. Good for homepages.
Job Single Full job detail view with a slide-in application panel and a "Report this job" control.
Job Stats Horizontal stat strip showing total jobs, companies, and candidates.
Recent Jobs Static list of the most recently published jobs. Good for sidebars or homepages.
Similar Companies A sidebar card listing companies related to the one being viewed.

WP Career Board Pro adds more blocks, including AI Chat Search, Application Kanban, Credit Balance, Featured Candidates, Featured Companies, Job Alerts, Job Map, My Applications, Open to Work, Resume Builder, Resume Map, Resume Search Hero, and Resume Single. See the Pro documentation for the full Pro blocks reference.

Adding a Block to a Page

  1. Open any page in the WordPress editor (Gutenberg)
  2. Click the + button to add a block
  3. Search for "Career Board" or the block name
  4. Click the block to insert it

Block Inserter - Career Board Blocks

For the main jobs page, use this block arrangement in order:

  1. Job Search - sits at the top, provides the search input
  2. Job Filters - sits below search, provides the filter dropdowns
  3. Job Listings - sits below filters, displays the results

All three blocks are connected - they automatically coordinate with each other on the same page. No configuration required.

Jobs Page Layout

Configuring Block Settings

Some blocks have settings you can adjust in the block sidebar:

Job Listings:

  • Job board - show only jobs assigned to a specific board (multi-board sites); "All boards" shows everything
  • Layout - grid (default) or list view; grid offers a 3 or 4 column choice
  • Jobs per page - how many jobs to show before the "Load more" button
  • Show filter sidebar - turn the search box and filter sidebar on or off
  • Show page heading - print the archive title from the block (off by default; leave off when the page already has a heading)
  • Filter sidebar - when the sidebar is on, reorder the filter groups (Job type, Experience, Category, Tags, Location, Job board, Salary) with the up/down arrows, and hide any you do not need with the eye toggle. Settings are per-block, so each Job Listings placement can have its own filter order.

Job Search Hero:

  • Layout - horizontal (default) or vertical
  • Show Category Filter, Show Location Filter, Show Job Type Filter - toggle each filter dropdown on or off

Job Form (Single-Page):

  • Board - target a specific board (multi-board sites only). Single-board sites can leave this at 0 and the default board is used.
  • Show Company Field - show or hide the company name field (on by default; useful to hide for staff-only embeds where the company is implied)
  • Compact - tighter vertical rhythm for sidebars and modals

Featured Jobs:

  • Jobs per page - how many featured jobs to display (default: 3)
  • Title - optional heading above the grid
  • Show "View All" link - toggle the link to the full job board

Recent Jobs:

  • Count - how many recent jobs to list (default: 5)
  • Show "View All" link - toggle the link to the full job board

Company Archive:

  • Companies per page - how many companies per page (default: 20)
  • Layout - grid or list

Job Stats:

  • Toggle Show Jobs, Show Companies, Show Candidates independently to display only the counts you want.

To access these settings, click the block in the editor and look at the Block panel in the right sidebar.

The Setup Wizard vs Manual Setup

The Setup Wizard creates pages with the correct blocks already placed. You only need to add blocks manually if:

  • You want to embed the job board on an existing page
  • You want a custom layout or custom page template
  • You dismissed the wizard

Tip: If the Setup Wizard already created your pages, you don't need to add blocks manually. Check Career Board → Settings → Pages to see which pages are currently assigned.

Using Shortcodes (Classic Editor)

If you're using the Classic Editor or a page builder that doesn't support Gutenberg blocks, you can use shortcodes instead. Every Free block has a shortcode equivalent:

Shortcode Block
[wcb_job_listings] Job Listings
[wcb_job_search] Job Search
[wcb_job_search_hero] Job Search Hero
[wcb_job_filters] Job Filters
[wcb_job_form] Job Form (4-step wizard)
[wcb_job_form_simple] Job Form (Single-Page)
[wcb_job_single] Job Single
[wcb_employer_dashboard] Employer Dashboard
[wcb_candidate_dashboard] Candidate Dashboard
[wcb_employer_registration] Employer Registration (alias: [wcb_registration])
[wcb_company_archive] Company Archive
[wcb_company_profile] Company Profile
[wcb_job_stats] Job Stats
[wcb_recent_jobs] Recent Jobs
[wcb_featured_jobs] Featured Jobs
[wcb_similar_companies] Similar Companies
[wcb_job_alert_card] Job Alerts CTA

Simply paste the shortcode into any page or post content area. The shortcode renders the same output as its Gutenberg block counterpart. Every shortcode also accepts the block's attributes (for example [wcb_job_listings boardId="42" perPage="6"]), so you can scope a block from a page builder without writing custom code.

Day-1 Quickstart Workflow

You've installed the plugin. Now what?

This is the shortest path from "fresh install" to "first job posted, first applicant reviewed." Five tasks, in order, plus where to go next when each is done.

1 - Finish the setup wizard

If you skipped the wizard during activation, re-run it from Career Board → Settings using the Run Setup Wizard button in the page header. The wizard:

  • Creates the six required pages (Find Jobs, Post a Job, Employer Registration, Employer Dashboard, Candidate Dashboard, and Companies).
  • Optionally installs sample data (3 companies, 8 jobs, and all taxonomy terms) so you can see real-looking content before you start typing your own.

Skip if: you've already completed it. Verify under Career Board → Settings → Pages that all six pages are mapped.

2 - Add the menu items your site needs

Open Appearance → Menus and add at least:

  • For Jobs/find-jobs/
  • For Employers/post-a-job/ or /employer-dashboard/
  • For Candidates/candidate-dashboard/
  • Companies/companies/

A career-board site that doesn't surface these on the main navigation silently loses both candidates and employers - they can't find the pages even when they exist.

3 - Post your first job (yourself, as admin)

Treat this as a smoke test of the whole pipeline.

  1. Go to /post-a-job/ (or click "Post a Job" from your menu).
  2. Fill the form with a real-looking listing - title, company, description, salary range, location, category.
  3. Submit. If moderation is on (Auto-Publish Jobs off), the job lands in Career Board → Jobs → Pending Review. Approve it.
  4. Visit /find-jobs/ - your job appears in the listing.
  5. Click into it - the single job page should look the way you want candidates to see it. If something looks wrong (e.g. company info missing), it's worth fixing now before you invite real employers.

4 - Apply to it (yourself, as a test candidate)

  1. Log out, or open a private window.
  2. Register a test candidate account at /employer-registration/ and choose Find a Job. (Or apply as a guest - guest applications are on by default in Free.)
  3. Apply to the job you just posted. Upload a real resume PDF and write a real cover letter - see what the experience feels like.
  4. Switch back to admin. Go to Career Board → Applications. Your test application should be there.
  5. Click into it. This is the screen your real employers will see when they review applicants. If you don't like how it looks, tweak the Application Details widget order (admin guide covers customization).

5 - Decide on moderation, credits, emails

Three settings that determine the day-2 experience:

  • Moderation (Career Board → Settings → Job Listings, the "Auto-Publish Jobs" toggle). Leave it off to require admin approval, or turn it on to auto-publish. Most marketplace sites use approval; most internal job boards auto-publish.
  • Credits (Pro only - Career Board → Settings → Credits). Turn on if you want to charge employers per posting using the built-in credit system.
  • Email notifications (Career Board → Settings → Emails). Make sure the candidate "application received" and employer "new application" emails are configured - they're how your candidates know they successfully applied and how your employers know to log in.

You're ready

Once steps 1-5 are done, the site is operationally ready. Real employers can register, post jobs, and review applicants. Real candidates can browse, apply, and track their applications.

What comes next depends on what you're building:

If you're running... Read next
A community / public job board for-employers/02-post-a-job.md - the full employer flow
A paid job board admin-guide/06-credit-system.md - credit setup
An internal team hiring board admin-guide/01-settings.md - auto-publish + role config
A site with existing classic-editor pages for-employers/11-page-builder-embeds.md - shortcodes

Troubleshooting Day-1 issues

  • Pages 404 after wizard - flush rewrite rules: Settings → Permalinks → Save (no changes, just save).
  • Apply button missing on jobs - the job must be published and open (not expired or closed). Guest applications are enabled by default in Free, so visitors can apply without an account. If you turned on Require Candidate Role (Settings -> Job Listings), only users with the Candidate role can apply.
  • No "Post a Job" link for employers - the employer needs the wcb_post_jobs capability. Site admin has it by default; for other users, grant it via the Users page or use a role manager.
  • Emails not arriving - your site's transactional email isn't set up. Install an SMTP plugin (FluentSMTP, WP Mail SMTP, etc.) and configure a real sending domain. Career Board's emails go through wp_mail like every other plugin.

Installing & Activating WP Career Board Pro

Pro feature - Requires a WP Career Board Pro license from wbcomdesigns.com.

WP Career Board Pro is an add-on plugin. It requires the free WP Career Board plugin to be installed and active first.

Step 1: Install the Pro Plugin

  1. Log in to your account at wbcomdesigns.com
  2. Go to My Account → Downloads
  3. Download wp-career-board-pro.zip
  4. In your WordPress admin, go to Plugins → Add New → Upload Plugin
  5. Select the downloaded zip and click Install Now
  6. Click Activate Plugin

If the free plugin is not active, activation will be blocked with an error message. Install and activate WP Career Board (free) first, then retry.

Step 2: Activate Your License

  1. Go to Career Board → Settings → License
  2. Paste your license key in the License Key field
  3. Click Activate License

A confirmation shows your license status, expiry date, and how many sites are using this license.

License Statuses

Status Meaning
Active Valid license, updates available
Expired License period ended - plugin still works but no updates
Inactive Key entered but not yet activated on this site
Invalid Key does not match any license
No activations left All license slots used - deactivate from another site first

License Tiers

Tier Sites
Single Site 1 site
Business 5 sites
Agency Unlimited sites

Deactivating

To move your license to a different site:

  1. Go to Career Board → Settings → License
  2. Click Deactivate License
  3. Activate on the new site

You can also manage all site activations from your account at wbcomdesigns.com.

Renewing

The plugin continues to work after expiry - you just stop receiving updates. To renew, log in to wbcomdesigns.com → My Account → Licenses → Renew.

What Activates with Pro

On activation, WP Career Board Pro:

  • Creates additional Pro database tables
  • Adds Pro settings tabs to Career Board → Settings
  • Registers additional Pro blocks in the block inserter
  • Enables the Resume Builder, Field Builder, Application Pipeline, Credit System, Multi-Board, Job Alerts, Job Map, and AI modules

Pro Setup Wizard

After activating the Pro plugin, a Pro Setup Wizard runs automatically to configure Pro-specific settings (pipeline stages, credits, resume page, etc.). This wizard appends its own steps to the standard wizard using the wcb_wizard_steps filter.

If the Free wizard already ran, the Pro wizard renders as a focused mini-wizard that handles only the Pro steps. You can re-run it any time from Career Board → Settings → Run Setup Wizard.

What's New in 1.7.0

WP Career Board and WP Career Board Pro ship in lockstep at 1.7.0. Install both updates together. This page highlights the customer-facing changes across the 1.5.0-1.7.0 and 1.3.0-1.4.x cycles. For the full line-by-line history, see the changelog in readme.txt.

1.7.0

  • New - Full mobile REST API for companion apps, including an app-config endpoint and viewer-relative fields on job cards.
  • New - Members can report other members, and site owners can block members and suspend candidates.
  • New - Members can delete their own account from within the app.
  • New - Guest applications are linked to a member account automatically when someone registers with the same email address.
  • New - Server-side content filtering for job listings.
  • Improve - Employers can see and manage their jobs and applications before creating a company profile.
  • Improve - Accessibility pass across the frontend with stronger text contrast and 40px minimum tap targets.
  • Improve - Faster on large sites through indexed application lookups, a version-keyed company-list cache, and primed user caches that remove per-row lookups.
  • Improve - Old job-view records are pruned automatically on a daily schedule.
  • Fix - The employer dashboard no longer shows a "set up your company profile first" prompt next to a list of the employer's existing jobs.
  • Fix - The public company directory reflects brand edits (tagline, industry, size, location) immediately instead of after a cache delay.
  • Fix - The jobs archive no longer returns a 404 after the plugin is reactivated.
  • Fix - CSV exports are compatible with PHP 8.4 and later.
  • Security - Job listing and application detail reads are scoped to their owner.
  • Security - Blocked members can no longer see listings or single jobs on the server-rendered frontend.
  • Compat - Aligned with WP Career Board Pro 1.7.0. Install both updates together.

1.6.0

  • New - The plugin is now fully translation-ready and bundles German, French, Spanish, Dutch and Korean translations; every interface string loads through WordPress's standard translation system.
  • New - Notification email bodies are now editable per template from the Emails settings, each with a ready-to-use default.
  • Fix - Notification emails no longer send with an empty body; the message body falls back to a sensible default when left blank.
  • Fix - The "Manage License" link is back on the WP Career Board plugins-screen row.
  • Compat - Aligned with WP Career Board Pro 1.6.0. Install both updates together.

1.5.0

  • Improve - Unified the admin colour tokens onto the same canonical namespace as the frontend, so admin and frontend theme consistently from one source.
  • Improve - Admin buttons now meet the 40px minimum tap target, and the bookmark, layout, view-switch and settings-toggle controls show a keyboard focus ring.
  • Improve - Admin status badges and the application detail screen now use the semantic colour tokens.
  • Fix - Tinted banners (onboarding notice, form success message, status badges) are now readable in BuddyX and BuddyX Pro dark mode instead of showing light text on a light background.
  • Fix - The recommended jobs grid no longer collapses its columns to zero width.
  • Fix - The settings toggle knob and setup-wizard controls now position correctly under right-to-left languages.
  • Compat - Aligned with WP Career Board Pro 1.5.0. Install both updates together.

1.4.6

  • Compat - Aligned with WP Career Board Pro 1.4.6, which reworks the Field Builder so custom fields are defined once and applied to every board. The free plugin has no functional changes in this release.

1.4.5

  • Fix - BuddyX 5.1 theme compatibility. WP Career Board now maps its colors to BuddyX 5.1's token system (and dark mode), so dashboard navigation labels, "View all" links and sidebar buttons render legibly instead of white-on-white or as solid coral pills.
  • Fix - Custom fields added with the Pro Field Builder now render and save correctly on forms for every field type - dropdown, multi-select, date range, salary range, video URL, file link, location and repeater. Several previously rendered as a plain text box and some did not save.

1.4.4

  • Fix - The empty-state "Clear filters" button label stays legible under themes that force a button text color (such as BuddyX). It previously rendered blank where the theme painted the label the same color as the button background.

1.4.3

  • New - The Job Listings block filter sidebar is now customizable. In the block settings you can reorder the filter groups (Job type, Experience, Category, Tags, Location, Job board, Salary) and hide any you do not need. Settings are per block, so each Job Listings placement can differ.
  • Improve - WP Career Board now adapts to BuddyX and BuddyX Pro 5.1 light and dark color modes. Card avatars, dashboards, buttons, and widgets re-color correctly in dark mode (previously only Reign's dark mode was handled).
  • Fix - The Job Listings block no longer emits PHP warnings when it renders with no matching jobs.
  • Dev - New wcb_notification_created action fires whenever a notification is created, so a central notification center (such as BuddyNext) can mirror Career Board notifications.

1.4.2

  • Fix - Banning an employer now takes effect. The Employers admin screen (Career Board -> Employers) gains Ban and Unban actions (per-row and bulk) plus a Status column. Banning an employer immediately removes every Career Board ability from that account.

1.4.0 - AI-assisted hiring and a Kanban board

This is the largest release of the cycle. The headline is AI-assisted hiring on the dashboards, a List / Board (Kanban) view for applications, and the change that lets any logged-in member apply without a dedicated Candidate role.

Any logged-in member can apply

Any logged-in member can now apply to jobs, save jobs, build a resume (Pro), and use the candidate dashboard without being given a separate Candidate role - ideal when the job board is part of a community site. If you want stricter separation, turn on Require Candidate Role under Career Board -> Settings -> Job Listings (or use the wcb_candidate_requires_role filter) to reserve the candidate experience for the Candidate role.

List / Board toggle on the employer dashboard

The Employer Dashboard Applications tab now has a List / Board toggle. The Board groups applicants into status columns - Submitted, Reviewing, Shortlisted, Hired, and Rejected. Drag a card to change an applicant's status, and the board, list, status emails, and AI ranking all stay in sync. (Pro adds custom hiring stages on top of this built-in board.)

Employer dashboard applications

AI hiring tools (require Pro and an AI provider)

WP Career Board exposes AI hooks that Pro answers when an AI provider is configured:

  • Applicant ranking - rank a job's applicants by AI fit. Each applicant shows a fit-score badge, the list sorts best-first, and the applicant detail shows the reasoning.
  • TL;DR summaries - each applicant shows a one-line summary on load once scored.
  • Recommended for you - the Candidate Dashboard overview shows a set of AI-matched jobs.
  • Write with AI - the apply panel can draft a cover letter from the candidate's resume and the job, ready to edit before applying.
  • Generate with AI - the job form can auto-generate a structured job description (headings, paragraphs, and bullet lists).

Sample data without re-running the wizard

You can install or remove the demo/sample data straight from Career Board -> Settings, without re-running the setup wizard.

Notifications panel redesign

The dashboard Notifications panel was redesigned with clearer read and unread states, Mark all read and Clear all controls, and an always-visible per-row delete button (40px tap target on mobile). Notifications that pointed at the homepage now render non-clickable instead of bouncing to the home page.

1.3.0 - Account self-service and clearer moderation

Account Settings in the dashboard

Candidates and employers can update their display name and email and change their password directly in the dashboard, instead of being sent off to wp-login.

Candidate dashboard overview

Rejected jobs and Resubmit

Rejected job listings now show as "Rejected" (not "Draft") in the employer dashboard, with a Resubmit action. Resubmitting sends the job back for admin approval instead of publishing it directly.

My Jobs and applications fixes

  • A newly posted job appears in My Jobs immediately, without a manual page reload.
  • A job posted before you saved a company profile is adopted into My Jobs when the company is created.
  • Saving a company from its profile page persists across reloads.

Email and notification quality

The Test Send button on the Emails settings tab (Career Board -> Settings -> Emails) succeeds even when a template is toggled off, so admin previews no longer report a false "Failed". Test sends are logged separately so they do not pollute production delivery metrics.

Emails settings tab

Upgrade notes

  • Lockstep: install Free 1.4.3 and Pro 1.4.3 together. The Pro dependency check refuses to load against an older Free.
  • Versions: the WCB_VERSION and WCBP_VERSION constants both move to 1.4.3. The stable tag in readme.txt matches.
  • No data migration is required for the 1.4.x updates.

For Employers

How employers post jobs, review applications, and manage hiring.

Employer Overview

Employers are businesses or individuals who post jobs and manage applications on your job board. This section covers everything an employer can do.

Employer Dashboard Overview

What Employers Can Do

  • Register an account with the Employer role
  • Post new jobs using a guided multi-step form, or a single-page form
  • Manage all their job listings (edit, close, re-open, resubmit)
  • Review applications in a list or a drag-and-drop Board (Kanban) view
  • Set up and edit a public company profile with a live preview
  • Bookmark jobs, companies, and candidate resumes
  • Update their own display name, email, and password from the dashboard
  • Receive email notifications for new applications

The Employer Role

When a user registers as an employer, they get the Employer role. This gives them access to the Employer Dashboard, a single-page app with a left sidebar grouped into sections rather than a row of top tabs. The sidebar items are:

  • Dashboard (Overview) - summary stat cards and quick actions
  • JOBS
    • My Jobs - manage all job listings (with a count badge)
    • Post a Job - submit a new job using the multi-step wizard
  • HIRING
    • Applications - review applicants in List or Board view (with a count badge)
  • COMPANY
    • Profile - set up the public employer page
    • Public Page - a link that opens your live company page in a new tab
  • CREDITS (only shown when the Credit System is enabled)
    • Balance - your current credit balance
    • Buy Credits - appears when the admin has set a purchase page
  • MY SAVES
    • Saved Jobs, Saved Companies, and Saved Resumes (Saved Resumes appears only when the resume feature is active)
  • ACCOUNT
    • Settings - display name, email, and password
    • Notifications - appears when the in-dashboard notification bell is enabled

Admins can also manually assign the Employer role to any user from Users → Edit User in wp-admin.

How Applications Reach Employers

When a candidate applies to a job, the employer sees the application immediately in their dashboard. They get:

  • Applicant name and email
  • Application status (Submitted / Reviewing / Shortlisted / Rejected / Hired)
  • Submission date
  • A direct link to the applicant's profile (if they are a registered candidate)

Section Contents

Post a Job

Jobs are posted from within the Employer Dashboard - there is no separate "Post a Job" page. Navigate to your dashboard and click Post a Job in the sidebar (under the JOBS section), or use the Post Your First Job button on the Overview tab.

Job Form - Step 1

Before You Post

Make sure you are logged in as a user with the Employer role. If you are not logged in, the dashboard will show a prompt to register or log in.

Step-by-Step: Posting a Job

The job form is a 4-step wizard that walks you through each section of the listing.

Step 1 - Basics

Enter the core information about the role:

  • Job Title - the position name (required)
  • Job Description - full description of the role, responsibilities, and requirements

Step 2 - Details

Provide the specifics:

  • Location - city, state/country, or Remote
  • Salary - optional; enter a min and max range, with currency and period (yearly / monthly / hourly)
  • Job Type - Full-time, Part-time, Contract, Freelance, or Internship
  • Experience Level - Entry, Mid, Senior, Lead, or Executive
  • Application Deadline - optional; date after which the job closes automatically
  • Apply URL - optional; an external link where candidates apply on your own site. When set, the public job page shows an "Apply on Company Site" button instead of the on-site apply form. The URL must start with http:// or https://.
  • Apply Email - optional; an address candidates can email to apply

Step 3 - Categories

Classify the job so candidates can find it:

  • Job Category - select the industry or function category
  • Tags - add relevant tags for better discoverability

Step 4 - Preview

Review all the information you entered across the previous steps. If everything looks correct, click Post Job to submit. (When editing an existing job, this button reads Update Job.)

Job Form - Review Step

After Submitting

If moderation is ON (default): your job is submitted for admin review. You will see a "Pending review" message. The job goes live after the admin approves it.

If moderation is OFF: your job is published immediately and appears on the job board.

You will receive a confirmation email when your job goes live.

Editing a Submitted Job

You can edit a pending or published job from your Employer Dashboard → My Jobs → Edit. Changes to a published job may require re-approval depending on your admin's settings.

Job Expiry

If your admin has set an expiry period (e.g., 30 days), your job will automatically close on that date. You will receive an email notification before it expires, and you can re-open it from your dashboard.

Single-Page Form - when the 4-step wizard is overkill

The default post-a-job experience is a 4-step wizard. For some embed points the wizard is too tall: sidebars, modal overlays, partner pages, single-page sites, and classic themes with limited vertical real estate. WP Career Board ships a second block, Job Form (Single-Page), that puts every field on one screen.

It submits to the same /wcb/v1/jobs endpoint, honours the same wcb_job_form_fields filter for custom fields, and respects the same employer-role gate. The only thing it does not support is edit mode - editing a job always routes through the wizard from the Employer Dashboard.

Block settings

  • Board - target a specific board (multi-board sites only)
  • Show Company Field - toggle the company name field on or off (on by default)
  • Compact - tighter vertical rhythm for narrow embed contexts

Adding the single-page form

In Gutenberg, search for Job Form (Single-Page) in the block inserter. In classic editors or page builders, use the shortcode:

[wcb_job_form_simple]
[wcb_job_form_simple boardId="42" showCompanyField="false" compact="true"]

When to use which: keep the wizard on your primary "Post a Job" page - the dashboard already places it for you. Reach for the single-page form when you need a job form alongside other content - homepage hero, partner page, sidebar widget, or modal overlay.

Manage Your Jobs

The My Jobs tab in the Employer Dashboard shows all the jobs you have posted, with quick actions to manage each one.

Employer Dashboard - My Jobs Tab

Accessing Your Jobs

  1. Go to the Employer Dashboard page (created by the Setup Wizard)
  2. Click My Jobs in the sidebar (under the JOBS section). Its badge shows your total job count.
  3. You will see a list of all your jobs with their current status

Since 1.7.0, My Jobs and your Applications are available as soon as you have jobs on file, even if you haven't created a company profile yet. The dashboard no longer nags you to "set up your company profile first" while you're staring at a list of jobs you've already posted - that prompt only appears once, before you have any jobs, and you'll still need a company profile before posting a new job.

Filtering by Status

A row of filter pills at the top of My Jobs lets you narrow the list:

All, Live, Draft, Pending, Closed, Rejected

Job Statuses

Status Meaning
Published (Live) Live on the job board, visible to candidates
Draft Saved but not yet submitted for review
Pending Submitted, waiting for admin approval
Rejected The admin declined the job; you can edit and resubmit it
Closed No longer accepting applications; hidden from the board
Expired Passed the expiry date; same as Closed

Actions per Job

Each job row shows quick-action buttons that change based on the job's status:

  • View ↗ - opens the public job listing in a new tab
  • Edit - opens the job for editing in the job form
  • Close - closes the job and stops accepting applications (active jobs only)
  • Publish - submits a saved draft for approval (draft jobs only)
  • Resubmit - sends a rejected job back for admin approval (rejected jobs only). It does not publish directly; it returns to Pending.
  • Reopen - puts a closed or expired job back on the board (inactive jobs only)

Job Card Actions

Editing a Job

  1. Click Edit on any job
  2. The multi-step Job Form opens pre-filled with the current data
  3. Make your changes and click Update Job

Note: If moderation is enabled, edits to a published job may require re-approval. The job stays live while under review.

Closing a Job

Click Close to stop accepting new applications. The job is removed from the job board listing but the data is preserved. You can reopen it later.

Use this when:

  • You have filled the position
  • You want to temporarily pause applications

Application Count

Each job card shows the number of applications received. Click the count to jump directly to the Applications view for that job.

Review Applications

The Applications view in the Employer Dashboard lets you work through the applicants for each of your jobs. You pick a job, then review its applicants in either a List or a Board (Kanban) view and update each applicant's status.

Employer Dashboard - Applications View

Accessing Applications

  1. Open the Employer Dashboard
  2. Click Applications in the sidebar (under the HIRING section). Its badge shows your total applicant count.
  3. Select a job from the job selector at the top. Until you select a job, the view prompts you to choose one.

List view vs Board view

A List / Board toggle sits above the applicants:

  • List - a split panel: applicants on the left, the selected applicant's full detail (cover letter, resume, status) on the right.
  • Board - a Kanban board with one column per status (Submitted, Reviewing, Shortlisted, Hired, Rejected). Drag an applicant card from one column to another to change their status. The board, the list, and the status emails all stay in sync.

Both views are included in the free version.

What You See per Applicant

Each applicant row or card shows:

  • Applicant name and initials avatar
  • Email address (in the detail panel)
  • Which job they applied to
  • Application date
  • Current status - see statuses below

Filtering by Status

Status filter pills above the list let you narrow the applicants for the selected job:

All, New, Reviewing, Shortlisted, Rejected, Hired (each pill shows a live count).

Application Statuses

Status When to use
Submitted Application received - not yet reviewed
Reviewing You are actively reviewing this candidate
Shortlisted Candidate is worth moving forward
Rejected No longer considering this applicant
Hired Offer accepted - position filled

Updating Application Status

In List view, change an applicant's status from the status control in the detail panel. In Board view, drag the card to a different column. Either way the change is saved immediately - no page reload - and the candidate is notified ("Status updated. The candidate has been notified.").

Ranking applicants by AI fit (Pro)

When WP Career Board Pro is active and an AI provider is configured, a Rank by AI fit button appears above the applicant list. It scores each applicant against the job, sorts the list best-first, shows a fit-score badge on each applicant, and surfaces a one-line TL;DR summary plus the reasoning in the detail panel. Without Pro and a provider this button does not appear.

With WP Career Board Pro: the fixed five-status system is replaced by a fully customizable stage pipeline (for example Screening - Interview - Offer - Hired/Rejected). The free List and Board views still apply; Pro lets you define the stages those columns represent. See Application Pipeline.

Reviewing the resume

The detail panel shows the applicant's cover letter and, when a resume was attached, View Resume and Download Resume links. If the applicant is a registered candidate with a public profile, you can also open their full profile to read their experience and education on the site.

Contacting Applicants

Use the applicant's email address to reach out from your mail client. All communication happens outside the plugin - WP Career Board does not have a built-in messaging system in the free version.

When Candidates Withdraw

If a candidate withdraws their application, it is permanently deleted and will no longer appear in your application list.

Company Profile

Every employer gets a public Company Profile page that candidates can browse. It shows your company information and all your active job listings in one place.

Company Profile - Public Page

What the Company Profile Shows

  • Company name, logo, and tagline
  • Industry, company size, and company type
  • HQ location and founded year
  • Website and social links (LinkedIn, X/Twitter)
  • "About the Company" description
  • All currently active job listings from this company

Candidates can click through to any individual job listing directly from your company page.

Setting Up Your Profile

Edit your company profile from the Employer Dashboard:

  1. Open the Employer Dashboard
  2. Click Profile in the sidebar (under the COMPANY section)
  3. Fill in your company details. A Live Preview pane shows how the page will look as you type.
  4. Click Save Profile. You will see "Profile saved successfully."

To view the published page, use the Public Page link in the sidebar, which opens your company profile in a new tab.

Company Profile - Edit

Profile Fields

Field Required Notes
Company Name Yes Displayed as the page title
Company Logo No JPEG, PNG, GIF, or WebP. Upload becomes available after the profile is first saved.
Tagline No One-line description shown on listings and company cards
About the Company No Multi-paragraph rich-text description
Industry No Shown as a tag on company cards
Company Size No 1-10, 11-50, 51-200, 201-500, 501-1,000, 1,001-5,000, or 5,000+ employees
Company Type No Public, Privately Held, Self-Employed/Freelance, Non-profit, Government, Educational, or Partnership
HQ Location No e.g. San Francisco, CA
Founded Year No Numeric year
Website No Shown as a clickable link
LinkedIn No Company LinkedIn URL
X (Twitter) No Company X/Twitter URL

Only Company Name is required. You can save with just the name and fill in the rest later.

Company Profile URL

Your company profile URL is automatically generated from your company name: yourdomain.com/company/your-company-name/

Who Sees the Company Profile

The Company Profile page is public - any visitor can see it, even without an account. The Company Archive page (if enabled) lets visitors browse all companies on your board.

Tip: A complete company profile with a logo and description significantly increases candidate trust and application rates.

Application Pipeline

Pro feature - Requires WP Career Board Pro.

The Application Pipeline replaces the free version's status system (Submitted / Reviewing / Shortlisted / Rejected / Hired) with a fully customizable ATS-style stage workflow and a visual Kanban board.

Application Pipeline - Kanban Board

Free vs Pro

Free Pro
Application stages Fixed: Submitted, Reviewing, Shortlisted, Rejected, Hired Any custom stages you define
Pipeline view List + Board (Kanban) List + Board (Kanban)
Terminal outcomes Rejected / Hired Hired / Rejected (configurable, per-board)
Stage history No Yes

The List and Board (Kanban) views both ship in the free version - see Review Applications. What Pro adds is the ability to define and rename the stages those board columns represent, instead of the fixed five statuses.

Default Stages

When you first enable the Pipeline, these stages are created automatically:

  1. Submitted (starting stage)
  2. Screening
  3. Interview
  4. Offer
  5. Hired (terminal - outcome: Hired)
  6. Rejected (terminal - outcome: Rejected)

You can rename, add, reorder, or delete any of these.

Configuring Your Stages

Go to WP Career Board → Boards, then open the board you want to configure and click the Stages tab.

Adding a Stage

  1. Click + Add Stage
  2. Enter the stage name (e.g., "Technical Test")
  3. Choose a color for the stage badge
  4. Toggle Terminal stage on if this is a final outcome
  5. If terminal, select the outcome: Hired or Rejected
  6. Click Save

Stage Colors

Choose colors that give instant visual meaning:

  • Green tones → positive stages (Offer, Hired)
  • Red tones → rejections
  • Blue/gray tones → neutral stages (Screening, Interview)

Terminal Stages

When you move a candidate to a terminal stage:

  • Their application status is automatically set to Closed
  • If outcome is Hired - the job's hired counter increments
  • If outcome is Rejected - the candidate receives a rejection email (if enabled)

You must have at least one Hired terminal stage and one Rejected terminal stage.

Reordering and Deleting

  • Reorder: Drag and drop stage rows - order determines Kanban column order (left to right)
  • Delete: If applications are in that stage, you'll be asked to move them to another stage first

Using the Kanban Board

  1. Open Employer Dashboard → Applications
  2. Select a job, then click the Board option in the List / Board toggle

Each column is a stage. Drag applicant cards between columns to move candidates through your pipeline. Click any card to open the full application details.

Bulk Moving

In list view, select multiple candidates with checkboxes, then use the Move to Stage dropdown to move all at once.

Per-Board Stages

If you use the Multi-Board Engine, each board has its own stage configuration. Go to WP Career Board → Boards, select the board, and configure its stages independently.

Find Resumes

Pro feature - Requires WP Career Board Pro.

The Find Resumes block displays a public-facing archive of candidate resumes. Employers and admins can browse candidate profiles filtered by skills, location, and job title - without waiting for candidates to apply.

How It Works

Candidates build their resumes using the Resume Builder. When a candidate sets a resume to Public, it appears in the Find Resumes archive. Resumes set to Private are never shown here.

Employers can browse the archive, filter by skills and location, and click through to a full resume page.

Adding Find Resumes to a Page

  1. Create a new page (e.g., "Find Candidates" or "Resume Database")
  2. In the WordPress editor, add the Find Resumes block
  3. Publish the page

No settings configuration is required - the block renders all public resumes automatically.

Filtering

Visitors can filter resumes by:

  • Skills - matches against the Skills section of each resume
  • Location - matches against the candidate's listed location
  • Job Title - keyword match against the candidate's most recent job title

Filters update the list without a page reload.

Candidate Privacy

Candidates control their resume visibility:

  • Private (default) - visible only to employers who receive an application from that candidate
  • Public - visible in the Find Resumes archive

Candidates can change visibility at any time from the Resume Builder or their dashboard.

Linking to Resume Single Page

When a visitor clicks a resume in the archive, they are taken to the Resume Single page - a full formatted view of that candidate's resume. The Resume Single block handles this display.

To enable this:

  1. Create a page with the Resume Single block
  2. Assign it in WP Career Board → Settings → Pages → Resume Page

Quick Job Form (single-page)

The Quick Job Form is a one-screen alternative to the multi-step job-form wizard. Drop it into any sidebar, modal, partner page, or page builder. Captures the core fields an employer needs to publish in one submit - no tab switching, no wizard navigation.

Sibling of the full Post a Job form (the 4-step wizard) - both share the same custom-field hook and persistence layer, so anything you add via wcb_job_form_fields appears on both surfaces.

When to use it

  • Embed in a sidebar widget so partners can post a job from any page on your site without navigating to the dashboard.
  • Drop into a modal triggered from a "Post a job" CTA on a marketing page.
  • Embed on a partner page on your own site so a logged-in employer can post without first navigating to the dashboard.
  • Onboarding flows where you want to capture the first job inline during account creation, not after.

The submitter must be logged in as a user with the Employer role (the same gate as the dashboard wizard).

How to add it

As a block

In the WordPress editor, add the Job Form (Single-Page) block. Available attributes:

Attribute Type Default What it does
boardId integer 0 Lock the form to a specific board (useful for multi-board sites)
showCompanyField boolean true Show or hide the company-name field
compact boolean false Tighter vertical rhythm for narrow embed contexts (sidebars, modals)

As a shortcode

For page builders or classic editor:

[wcb_job_form_simple]
[wcb_job_form_simple boardId="42"]
[wcb_job_form_simple showCompanyField="false" compact="true"]

Every Block attribute forwards to the shortcode using the same name. Page builders (Elementor, Divi, Bricks, Beaver Builder, classic editor) all support attribute passthrough.

As an Elementor / Divi / Bricks / Beaver Builder embed

Use the shortcode widget in your page-builder of choice. See the Page-builder embeds guide for the full attribute reference shared by every shortcode.

Fields captured

Field Required Note
Board No Shown only on multi-board sites (or hidden when boardId locks the form)
Company No Toggle with showCompanyField
Job Title Yes
Job Description Yes Rich text
Category No Job category select
Job Type No Full-time / Part-time / Contract / Freelance / Internship
Location No Free text
Experience No Entry / Mid / Senior / Lead / Executive
Skills / Tags No Comma-separated tags
Salary range No min + max, currency, period (yearly / monthly / hourly)
Application deadline No Date picker
Apply URL No External apply link (must start with http:// or https://)
Apply Email No Address candidates can email to apply
Custom fields Optional Whatever your wcb_job_form_fields filter contributes

Fields specific to your industry can be added via the Custom fields filter - they'll appear on this form AND the multi-step form automatically.

What happens on submit

The form posts to the same REST endpoint as the multi-step form (POST /wcb/v1/jobs), so:

  • Moderation rules apply identically (jobs land in pending if moderation is enabled).
  • Featured-status, board assignments, and credit deduction flow through the standard pipeline.
  • BuddyPress activity-stream entries fire on approval (Pro).
  • Email notifications fire to whoever the site config dictates (admin moderator / employer-confirmation / etc.).

Limitations

  • Single-screen UX means there's no preview step before publish. Employers can still edit immediately afterward via the dashboard.
  • Multi-image uploads (company logos, banner art) are not part of this form - those still happen via the company profile editor.

Bulk Applicant CSV Export

Export selected applications from the admin list table to a UTF-8 CSV spreadsheet - one row per applicant, ready to drop into Google Sheets, Excel, or your ATS.

Where to find it

In wp-admin, navigate to Career Board → Applications. The list table ships a Bulk actions dropdown with an Export to CSV option.

How to use it

  1. Filter / search the list down to the applications you want (the status and job filters on the list table all work).
  2. Tick the row checkboxes (or the column-header checkbox to select the whole visible set).
  3. Open the Bulk actions dropdown, choose Export to CSV, click Apply.
  4. The browser downloads wcb-applications-YYYY-MM-DD-HHMMSS.csv.

Columns in the export

The CSV has these columns, in this order:

Column Source
ID Application post ID
Job ID Numeric ID of the linked job, for joining back to the jobs table
Job Title Linked wcb_job post title
Applicant Name Candidate display name, or the guest name for guest applications
Applicant Email Candidate user email, or the guest email
Status Application status slug (submitted, reviewing, shortlisted, rejected, hired)
Submitted Application post date
Cover Letter The cover letter text (multi-line preserved using CSV quoted-string semantics)
Resume URL Direct link to the uploaded resume file, when one was attached

Encoding

UTF-8 with a BOM so Excel renders non-ASCII names correctly without manual import-wizard configuration. Multi-line cover letters preserve newlines using standard CSV quoted-string semantics.

Permissions

The export is available on the admin Applications screen, and each row is included only for applications the current user can edit (the standard edit_post capability check per application). Site admins can export all; an employer reaching the screen exports only their own applications.

Your Credit Balance (Employer View)

If your site uses the Credit System, this is what you, the employer, see and how the flow works from your side. The admin-side setup is covered in admin-guide/06-credit-system.md.

This doc only applies when: your site admin has enabled the Credit System and you, as an employer, are required to spend credits to post jobs.

Where to See Your Balance

Open your Employer Dashboard. When the Credit System is enabled, a CREDITS section appears in the dashboard sidebar showing:

  • Balance - your current credit balance.
  • Buy Credits - a link that appears only when the admin has set up a purchase page.

The balance also appears as a banner on the Post a Job form when you're about to submit, so you don't have to leave the form to check. A low-balance notice shows when your balance dips below the threshold the admin set.

How Credits Are Spent

The cost depends on which Board you're posting to. Different boards can have different per-post prices (admin sets this up).

The sequence:

  1. You start filling the Post a Job form.
  2. The banner at the top reads, e.g., "Posting deducts 1 credit. Balance after: 99 (currently 100)."
  3. You submit the job.
  4. Credits are held - reserved but not yet consumed.
  5. If your site requires admin approval, the credits stay held until the admin acts.
  6. If approved - credits are deducted permanently.
  7. If rejected - held credits are released back to your balance.
  8. If you withdraw the job before approval, held credits are released.

Insufficient Credits

If your balance is below the cost when you try to submit:

  • The submit button is disabled.
  • The banner shows: "This board requires N credits. Your balance: M. Please purchase more credits."
  • A "Buy Credits" link appears (when the admin has configured a purchase page).

You can save the form as a Draft in this state - your job won't post, but the form contents are preserved so you don't have to re-type when you top up.

Buying Credits

The Buy Credits link sends you to whatever purchase page your admin configured (the admin sets this URL). It could be a checkout page, a pricing page, or any page the admin points it at. The link only appears when that purchase page has been set up.

Complete the purchase the way your admin's page asks. Once the purchase clears, credits are added to your balance and you can go back to posting your job.

If a payment is still pending (for example a bank transfer), credits are not added until the payment clears - check with your admin if you've paid but credits haven't appeared after a few minutes.

If the admin has enabled featured upgrades, you can pay extra credits to promote your job to the top of search results for a configurable duration. The "Featured" toggle appears on the Post a Job form with the credit cost shown next to it.

Featured listings expire automatically after the duration the admin configured (30 days by default). Once a featured job's window expires, the listing stays - it just loses the boost. To feature it again, post or edit the job and re-enable the Featured toggle.

Transaction Types

Behind your balance, the Credit System tracks each movement:

Type What it means
Top-up You bought credits (or the admin granted them)
Hold Credits reserved for a pending job
Deduct Credits consumed for an approved job
Refund Credits returned (job rejected or you withdrew)

If you ever dispute a charge, ask your site admin to check the ledger for your account - they can see every top-up, hold, deduction, and refund tied to your balance.

Refunds

If you posted a job that turned out to be wrong or got rejected, held credits return automatically. For an already-deducted job that the admin agrees should be refunded, contact your site admin - they can grant credits back to your account manually. Auto-refund of deducted credits is not available because the job has been live and received exposure.

Frequently Asked

Do credits expire?

By default no - your balance never expires. Some sites configure this differently (e.g., monthly membership credits that reset each cycle). Check with your admin if you're on a recurring plan.

Can I gift credits to a colleague at the same company?

Not directly. Credits are per-account. If your colleague is an employer at the same company, they need their own account and their own credits. Contact the admin if you want to share a pool - they can grant credits manually to either account.

I bought credits but they're not showing.

Wait 1-2 minutes (the dashboard caches balance briefly), then log out and back in. If still missing, send your admin the order number - they can verify the payment landed and grant the credits manually if the automatic flow didn't fire.

Page-builder Embeds (Elementor, Divi, Bricks, Beaver Builder)

Every WP Career Board block has a matching shortcode, and every shortcode now accepts the same attributes the block does. So if you build pages with Elementor, Divi, Bricks, Beaver Builder, or the classic editor, you can scope blocks the same way you would in the block editor.

Shortcode reference

Every WP Career Board block has a shortcode wrapper that accepts the same attributes. Use these in Elementor, Divi, Bricks, Beaver Builder, the classic editor, or anywhere a shortcode is accepted.

Block Shortcode
Job Listings [wcb_job_listings]
Job Search Hero [wcb_job_search_hero]
Job Form (multi-step) [wcb_job_form]
Job Form (single-page) [wcb_job_form_simple]
Job Search [wcb_job_search]
Job Single [wcb_job_single]
Job Filters [wcb_job_filters]
Featured Jobs [wcb_featured_jobs]
Recent Jobs [wcb_recent_jobs]
Job Stats [wcb_job_stats]
Company Archive [wcb_company_archive]
Company Profile [wcb_company_profile]
Candidate Dashboard [wcb_candidate_dashboard]
Employer Dashboard [wcb_employer_dashboard]
Employer Registration [wcb_employer_registration]
Similar Companies [wcb_similar_companies]
Job Alert Card [wcb_job_alert_card]
Modular Widgets [wcb_widget id="..."]

Back-compat alias: [wcb_registration] still works as a synonym for [wcb_employer_registration] - sites that already embedded the short form keep rendering. New pages should use the canonical tag.

Attribute passthrough

All shortcode attributes match the block attribute name (camelCase becomes lowercase-with-no-separator in some cases). For example:

[wcb_job_listings perPage="6" boardId="42" layout="list"]

Renders the same thing as the Job Listings block with perPage=6, boardId=42, layout=list.

Common scoping patterns

Show a board-scoped listing

[wcb_job_listings boardId="42" perPage="10"]

Only jobs assigned to board 42. Used on board-specific landing pages or partner pages.

Filter by custom meta

If you've registered a custom meta key via the wcb_jobs_allowed_meta_filters filter, you can scope a listing by that meta:

[wcb_job_listings metaFilter="industry:fintech" perPage="6"]

Embed a form on a marketing page

[wcb_job_form_simple showCompanyField="false" compact="true"]

A compact single-page job form with the company-name field hidden - handy in a narrow column or modal. See Quick Job Form for the full attribute list.

Render a single widget from the application screen

The new modular widget system on the Application Editor exposes its widgets as shortcodes too, so you can embed e.g. an applicant card on a partner profile page:

[wcb_widget id="applicant_card" application_id="987"]

Tips for page-builder users

  • Elementor - use the Shortcode widget, not "HTML". The HTML widget escapes shortcodes.
  • Divi - drop a Code module and paste the shortcode. The Visual Builder renders the live block.
  • Bricks - use the Shortcode element under Basic.
  • Beaver Builder - use the HTML module; Beaver Builder runs shortcodes through do_shortcode() automatically.
  • Classic editor - paste the shortcode anywhere. Works in posts, pages, custom post types, widgets.

All blocks render identically across these surfaces - same CSS, same Interactivity API behavior, same REST data flow.

Troubleshooting (Employers)

Common things employers hit, in plain language. If you're a site owner / admin, see admin-guide/07-troubleshooting.md for the admin-side debug path.

"I posted a job but it isn't showing up"

Three things to check, in order:

  1. Is it pending approval? Go to your Employer Dashboard → My Jobs. If the job is there with status "Pending" or "Under Review", the site is configured to require admin approval. Contact the site admin or wait for approval.
  2. Is it past the deadline? If you set an "Apply by" date in the past (or your draft sat too long and the date came and went), the job auto-expires. Open it from your dashboard and either extend the deadline or republish.
  3. Did the submit actually complete? Your dashboard shows every job you've created. If it's not there, the form didn't save - usually because of a network blip. Re-submit.

"Applicants aren't coming in"

Posting alone doesn't bring traffic. Check:

  • The job is on /find-jobs/ - visit it from a private window. If you can't find it there, candidates can't either.
  • Your job's URL has been shared. Share on LinkedIn, your company's social channels, internal Slack. New job boards build traffic over months.
  • The "Apply by" date isn't past. Expired jobs disappear from the default listing.
  • Your category, location, and type are typical search terms. A "Senior Frontend Engineer" gets more eyeballs than a job filed as "Other → Other".

"I keep getting 'Insufficient credits' when I try to post"

The site charges credits per posting. Your balance is on the Employer Dashboard → Credits panel.

  • You need to buy more. Click "Buy Credits" and complete the checkout. Once the order completes, your balance updates and you can post.
  • You bought credits but they didn't add. Wait 1-2 minutes (the dashboard caches the balance briefly). If still missing, contact the site admin with your order/receipt number.
  • Different boards cost different amounts. Switch to a cheaper board in the post-a-job form if it suits your role.

"My company profile changes aren't saving"

  • Edit from the dashboard. The company profile is edited from Employer Dashboard - Profile (then Save Profile), not from the public company page.
  • Company name is required. It's the only required field. If you clear it, the save is blocked with "Company name is required." All other fields are optional.
  • Save the profile before uploading a logo. Logo upload only becomes available after the profile has been saved once.
  • Special characters. If you pasted text with emoji or unusual characters and the save fails, copy the text into a plain editor first and re-paste.

"I'm not getting email notifications about new applications"

  • Check your spam folder. Most "missing email" complaints are spam-filter issues.
  • Confirm the email on your account is correct. Open Employer Dashboard - Settings (Account Settings) and check the Email field. New-application emails go to that address.
  • The site's email might not be configured properly. Contact the site admin and ask them to verify SMTP / email sending is working, and that the "new application" notification template is enabled in Career Board - Settings - Emails.

"The 'Apply on Company Site' button is missing from my job"

You set an external Apply URL but it isn't showing? Two things:

  • The URL must start with http:// or https://. Just typing company.com/careers won't work - the plugin filters out URLs without a scheme.
  • It only appears on the public job page. When you preview from your dashboard, the form's preview pane might not show it
    • check the live job URL instead.

"Candidates report the apply form is broken"

  • They might not be logged in. If your site requires login to apply, the Apply button shows but the form short-circuits. Tell candidates to register or log in first.
  • The site might have anti-spam (Turnstile/reCAPTCHA) enabled. Adblockers or strict browser settings can block the captcha script. If a candidate reports this, ask them to try in a different browser.
  • The resume file is too large. Default limit is 5 MB. Larger files get rejected at upload. Ask the candidate to resize/ re-export their PDF.

"I can't see the Pro features I'm paying for"

  • Pro plugin needs to be installed AND active. Site admin needs to do this - you can't enable it from your dashboard.
  • License needs to be activated. Site admin enters the license key under Career Board → Settings → License.
  • Some features depend on configuration. Job Map needs Google Maps API key, AI needs an OpenAI/Anthropic key, alerts need cron working. Site admin handles all this.

I'm stuck - what should I send my site admin?

Send them:

  1. The URL of the page where the problem happens.
  2. A screenshot of what you see vs. what you expect.
  3. The time and date the problem occurred (helps them check logs).
  4. Your user account email (so they can find your record).
  5. If applicable: your order/transaction number, the job title, the candidate's email.

Don't send screenshots of payment info or sensitive HR data - just the descriptive details.

For Candidates

How candidates find jobs, apply, and manage their profile.

Candidate Overview

Candidates are job seekers who browse listings and apply on your job board. They get a personal dashboard to manage all their activity in one place.

Candidate Dashboard Overview

What Candidates Can Do

  • Browse and search job listings
  • Filter jobs by category, type, location, experience level, and salary range
  • Bookmark jobs, companies, and (with Pro) candidate resumes to review later
  • Apply for jobs with a cover letter and a resume upload (PDF, DOC, or DOCX)
  • Track all applications and their statuses from a single dashboard
  • Receive email notifications when their application status changes, plus an in-dashboard Notifications tab when the notification bell is enabled
  • Edit a public profile, control its visibility, and update account details (name, email, password)
  • See Recommended for you jobs matched to their resume (Pro)
  • Build structured resumes with the Resume Builder (Pro)
  • Set up job alerts to get notified when matching jobs are posted (Pro)

Registration

Visit the Employer Registration page (which despite its name handles both roles) and choose "Find a Job" to register as a candidate. The heading on the registration block is "Join WP Career Board". You'll need:

  • First name and last name
  • Email address
  • Password (minimum 8 characters)

After registration, you're automatically logged in and redirected to your Candidate Dashboard.

Employers choose "Hire Talent" on the same page - one unified registration form for both roles.

Who Can Apply (Candidate Role Is Optional)

By default, any logged-in member can apply to jobs, save jobs, build a resume, and use the candidate dashboard - they do not need a dedicated Candidate role. This is ideal when the job board is part of a wider community or membership site where members already have accounts.

When a user registers through the "Find a Job" option, they are given the Candidate role as a convenience, but the candidate experience is available to every logged-in user regardless of role.

If you want stricter separation, turn on Require Candidate Role under Career Board → Settings → Listings. With it enabled, only users who hold the Candidate role (or an admin) can apply and use the candidate dashboard. Developers can override this per-site with the wcb_candidate_requires_role filter.

The candidate experience gives access to:

  • The Candidate Dashboard - Overview, My Applications, Saved Jobs, Saved Companies, Profile, Account Settings, and (when enabled) Notifications
  • The ability to apply for jobs and withdraw applications
  • The saved jobs, saved companies, and (with Pro) saved resumes lists
  • My Resumes, Resume Builder, and Job Alerts (Pro)

Admins can manually assign the Candidate role from Users → Edit User in wp-admin.

Guest Applications

Candidates can apply without creating an account. Guest applicants provide their name and email during the application. They receive email updates but do not have a dashboard.

Tip for your users: Creating an account gives candidates the ability to track all applications, save jobs, and build a profile. Encourage registration.

Section Contents

Finding Jobs

The job board gives candidates a fast, reactive way to browse and narrow down listings - no page reloads, no waiting.

Job Listings Page

Browsing the Job Board

Visit the Jobs page on your site. You will see a grid of all currently active job listings, each showing:

  • Job title
  • Company name and logo
  • Location
  • Job type (Full-time, Part-time, etc.)
  • Posted date
  • Salary (if provided by the employer)

Click any card to open the full job detail page.

Searching by Keyword

Use the Search bar at the top of the job board to find jobs by keyword. The search looks through job titles and descriptions. Results update as you type.

Job Search Bar

Filtering Jobs

Use the Filter dropdowns to narrow results by:

Filter Options
Category Industry or function (e.g., Engineering, Marketing, Design)
Job Type Full-time, Part-time, Contract, Freelance, Internship
Location Country, state, or city
Experience Level Entry, Mid, Senior, Lead, Executive
Salary Range A dual-handle slider to set a minimum and maximum pay. See Salary Range Filter.

You can combine multiple filters. Results update instantly after each selection.

To remove all filters at once, click Clear all in the filter bar.

Loading More Jobs

The job board loads a set number of jobs at a time (set by your admin). When you reach the bottom, click Load more to see additional listings.

Viewing a Job

Click any job card to open the full detail page. You will see:

  • Full job description
  • Company information with a link to the company profile
  • Application deadline (if set)
  • Salary range
  • Job type, location, and experience level
  • An Apply Now button to start the application

Job Single Page

When the site runs WP Career Board Pro with AI matching enabled, your Candidate Dashboard → Overview shows a Recommended for you list - jobs matched to the resume on your profile, labelled "AI-matched to your resume". This is in addition to browsing and searching the full board. The recommendations are hidden on Free-only installs and when AI matching is not configured.

Saving a Job for Later

Click the bookmark icon on any job card or job detail page to save it. Saved jobs appear in your Candidate Dashboard → Saved Jobs tab. Bookmarking works for any logged-in user (a dedicated Candidate role is not required).

You can remove a saved job at any time from the dashboard. You can also bookmark companies - those appear under Candidate Dashboard → Saved Companies.

Applying for Jobs

Applying is quick - candidates fill out a short form that slides in from the right side of the job listing page. No redirects, no new pages.

Application Panel - Slide-in Form

Before You Apply

You can apply as a guest (no account required) or as a logged-in member. By default any logged-in user can apply - a dedicated Candidate role is not required unless the site admin turns on Require Candidate Role.

Logged-in members get:

  • A dashboard to track all their applications
  • Saved application history
  • Email updates on every status change

How to Apply

  1. Open a job listing page
  2. Click Apply Now - an application panel slides in from the right
  3. Fill in the form fields
  4. Click Submit Application

Application Form Fields

Field Requirement
Full Name Required (pre-filled if logged in)
Email Address Required (pre-filled if logged in)
Cover Letter Optional by default - but strongly recommended
Select Resume Choose from your saved resumes (Pro)
Upload Resume Upload a PDF, DOC, or DOCX file. Default size limit is 5 MB; the site admin can raise it up to 20 MB. A resume is required to apply unless the admin turns that off.

When Pro is active, you'll see both options: pick an existing resume from your profile or upload a file directly. The " - or upload a file - " divider separates the two methods. If you pick a resume that was built in the Resume Builder and has no uploaded PDF, Pro generates and attaches a PDF for you automatically on submit.

Write your cover letter with AI (Pro)

When the site runs WP Career Board Pro with AI enabled, a Write with AI button appears next to the Cover Letter field. Click it to have the assistant draft a cover letter based on the job and your profile, then edit the text before submitting. The button is hidden on Free-only installs and when AI is not configured.

With WP Career Board Pro: employers can also add custom screening questions to each job.

What Happens After You Apply

  1. You receive a confirmation email with the job title and company name
  2. The employer receives a notification email about your application
  3. Your application appears in your Candidate Dashboard → My Applications with status Submitted
  4. Get notified about similar jobs - after submitting, you'll see a prompt to create a job alert based on this job's category, type, and location (Pro feature)

Withdrawing an Application

If you change your mind:

  1. Go to your Candidate Dashboard → My Applications
  2. Find the application you want to withdraw
  3. Click Withdraw

Withdrawing permanently deletes the application. It is removed from both your dashboard and the employer's view. You cannot resubmit after withdrawing.

Note for site owners: the Withdraw control is on by default and can be turned off under Career Board → Settings → Listings → Allow Withdraw. When it is off, candidates can no longer withdraw their own applications.

Application Limits

There is no limit to how many jobs a candidate can apply for on the free version.

Applying Without an Account

Guest applicants (no account):

  • Enter their name and email in the application form
  • Receive email confirmation
  • Cannot track their application status (no dashboard access)
  • Cannot withdraw their application

To track your application status, register as a candidate before applying.

My Applications

The My Applications tab in the Candidate Dashboard shows every job you have applied for and its current status.

Candidate Dashboard - My Applications Tab

Accessing My Applications

  1. Go to the Candidate Dashboard page
  2. The My Applications tab is active by default
  3. You will see all your applications listed newest first

Table format

The My Applications list renders as a semantic table with column headers, so the data is screen-reader friendly and copy/paste-able into a spreadsheet without losing structure. The list is part of the Candidate Dashboard block (shortcode [wcb_candidate_dashboard]); there is no separate applications-only shortcode.

My Applications table - candidate view

Column What it shows
Job Job title (linked to the listing) and company name
Status Coloured status badge - see the table below for each badge's meaning
Submitted Application date in your site's date format

On narrow viewports (under 480px container width) the table collapses to a card layout - each row's cells stack vertically with their column label in-place, so phones get the same data without a horizontal scrollbar.

What You See per Application

Each row shows:

  • Job title and company name
  • Application date
  • Current status - updated by the employer
  • A link to view the original job listing

Application Statuses

Status What It Means
Submitted Your application was received; the employer hasn't reviewed it yet
Reviewing The employer is actively looking at your application
Shortlisted You're being considered - the employer is interested
Rejected The employer is no longer considering your application
Hired Congratulations - you got the job
Withdrawn You withdrew this application; it is no longer active
Job Removed The job posting was taken down. Your application is preserved in your history, but no further action is expected.

Status updates: You will receive an email notification whenever your application status changes.

Withdrawing an Application

To withdraw from a role you are no longer interested in:

  1. Find the application in the list
  2. Click the Withdraw button
  3. Confirm in the prompt

Withdrawing permanently deletes the application. It is removed from both your dashboard and the employer's view. You cannot resubmit after withdrawing.

The Withdraw button only appears when the site allows it. Site owners can disable withdrawals under Career Board → Settings → Listings → Allow Withdraw (on by default).

Overview Panel

The Overview tab at the top of the dashboard shows a summary of your recent activity:

  • Total applications submitted
  • Number of shortlisted applications
  • Most recent applications
  • Recently saved jobs
  • Counts for Saved Jobs, and (with Pro) Resumes and Job Alerts, as clickable stat cards that jump to the matching tab

This gives you a quick snapshot without switching between tabs.

Saved Jobs

Save any job listing to your personal list so you can come back to apply when ready.

Candidate Dashboard - Saved Jobs Tab

Saving a Job

You can bookmark a job from two places:

From the job listings grid:

  • Click the bookmark icon in the top-right corner of any job card

From the job detail page:

  • Click the Save Job button on the listing page

Both require you to be logged in. Any logged-in user can save jobs - a dedicated Candidate role is not required. If you are not logged in, clicking the bookmark will prompt you to register or log in.

Viewing Your Saved Jobs

  1. Open the Candidate Dashboard
  2. Click the Saved Jobs tab

You will see all your bookmarked jobs listed with:

  • Job title and company name
  • Location and job type
  • Date saved
  • A Remove button

Removing a Saved Job

Click Remove on any saved job to delete it from your list. This does not affect any application you may have already submitted.

Applying from Saved Jobs

Saved jobs include a direct Apply Now link so you can apply without going back to the main listings page.

Tip: Use Saved Jobs as your personal shortlist. Browse the board first, bookmark the ones that interest you, then review your list and apply to the best matches.

Saved Companies and Saved Resumes

The dashboard groups all your bookmarks under a MY SAVES section in the sidebar:

  • Saved Jobs - jobs you bookmarked (covered above).
  • Saved Companies - bookmark a company from its profile to follow it. They appear under Candidate Dashboard → Saved Companies.
  • Saved Resumes - when WP Career Board Pro is active and public resumes exist, you can bookmark other candidates' resumes. This tab is hidden on Free-only sites.

All three lists are available to any logged-in user.

Limit

There is no limit to how many jobs, companies, or resumes you can save.

Resume Builder

Pro feature - Requires WP Career Board Pro.

The Resume Builder lets candidates create structured, multi-section resumes directly on your WordPress site - no PDF uploads, no external tools required.

Resume Builder - Full View

What Candidates Can Build

A resume is made up of sections. Each section holds structured entries:

Section What it stores
Professional Summary A free-text overview paragraph
Work Experience Job title, company, dates, description
Education Degree, institution, dates
Skills Skill name and optional proficiency level
Languages Language name and proficiency
Certifications Certificate name, issuing body, date
Links Portfolio, GitHub, LinkedIn, etc.

Admin Setup

Before candidates can use the Resume Builder, set it up in two steps:

  1. Create a page and add the Resume Builder block to it
  2. Go to WP Career Board → Settings → Pages and assign that page to the Resume Builder Page field

Once assigned, the Candidate Dashboard's My Resumes tab will link to this page automatically.

My Resumes Tab

Candidates access their resumes from Candidate Dashboard → My Resumes.

My Resumes Tab - Dashboard

From this tab, candidates can:

  • See all saved resumes with their last-updated date
  • Click Edit to open a resume in the builder
  • Click Create New Resume to start a new one
  • Click Delete to permanently remove a resume

Using the Resume Builder

The builder is organized into collapsible sections. Click any section header to expand it.

Resume Builder - Sections

Adding Entries

  1. Open any section (e.g., Work Experience)
  2. Click + Add Entry
  3. Fill in the fields
  4. Click Save on the entry

The entry appears as a compact row. Click it to expand and edit again.

Entry Fields

Work Experience: Job Title, Company, Start Date, End Date, "Currently working here" toggle, Description

Education: Degree / Qualification, Institution, Start Year, End Year, Field of Study

Skills: Skill name, Proficiency level (Beginner / Intermediate / Advanced / Expert)

Languages: Language name, Proficiency (Native / Fluent / Conversational)

Certifications: Certificate name, Issuing organization, Issue date

Links: URL, Label (e.g., "Portfolio", "GitHub")

Auto-Save

The Resume Builder saves each entry individually when you click Save on that entry. There is no global save button. A "Saved" confirmation briefly appears after each save.

Multiple Resumes

Candidates can create more than one resume - for example, one for engineering roles and one for management roles. The dashboard lists all resumes with their last-updated date.

Attaching a Resume to an Application

When a candidate applies for a job, they can select one of their saved resumes to attach. The employer sees the full structured resume on the application - not a PDF attachment.

Resume Visibility

  • Private (default) - visible only to the candidate and employers who receive applications from them
  • Public - visible in the Find Resumes employer archive

Candidates toggle visibility in the Resume Builder header.

Job Alerts

Pro feature - Requires WP Career Board Pro.

Job Alerts let candidates subscribe to saved searches and receive email notifications when new matching jobs are posted. Candidates set a frequency - instant, daily, or weekly - and WP Career Board sends digests automatically.

Three Ways to Create Alerts

1. From the Job Listings Page

When browsing jobs, click the "Alert me" button in the toolbar (next to the results count). This saves your current search query and active filters as a daily alert.

The button turns into "Alert saved" with a green checkmark to confirm.

2. After Applying for a Job

After submitting an application, you'll see a "Get notified about similar jobs" button below the success message. Clicking it creates an alert based on the job you just applied to - matching its category, type, and remote status.

3. From the Candidate Dashboard

Go to Candidate Dashboard → Job Alerts to view and manage all your alerts. From here you can also adjust the frequency of each alert.

Alert Frequency Options

Frequency When the email sends
Instant As soon as a matching job is posted
Daily Once per day (morning digest)
Weekly Once per week (Monday morning)

You can change the frequency at any time from the dashboard.

What Gets Matched

Alerts match new jobs against these criteria:

  • Keywords - job title contains your search terms
  • Category - job is in the same category
  • Job Type - full-time, part-time, contract, etc.
  • Location - matches the location taxonomy
  • Salary Range - job salary falls within your range
  • Remote - remote-only filter

Managing Alerts

From Candidate Dashboard → Job Alerts:

  • View all active alerts with their saved filters shown as pills
  • Change frequency using the dropdown (Instant / Daily / Weekly)
  • Delete an alert with the Delete button

The nav badge shows your total alert count.

Overview Stats

Your alert count also appears on the Dashboard Overview page alongside your Applications, Saved Jobs, and Resumes counts. Click the Job Alerts stat card to jump directly to the alerts tab.

Email Delivery

Alert emails are sent via the Notifications settings configured in WP Career Board → Settings → Notifications (From Name, From Email). Configure an SMTP plugin for reliable delivery.

Salary Range Filter

The Find Jobs page (/jobs/) now ships a salary range slider so candidates can narrow listings to roles paying within a specific range - instead of scanning every salary line manually.

Where it lives

On the Find Jobs page, in the filter panel below the search bar. The slider appears alongside the existing filters (location, job type, experience, category).

How it works

  • Drag the lower handle to set a minimum salary.
  • Drag the upper handle to set a maximum salary.
  • The active range shows as a chip pill above the listings - e.g. $60k-$120k/yr ✕. Click the ✕ to clear that filter.
  • Active range updates the listings live (no page reload).

The slider's range adapts to the salary distribution of currently listed jobs, so on a small board the slider tracks $0-$100k while on a senior-only board it might track $80k-$300k.

Periods

The slider respects whichever salary period each job is using - yearly, monthly, or hourly. Jobs without salary data are filtered out when the salary slider is active (set the slider to its widest range to include them again).

Currency

The slider currency follows the site's default currency (set under Career Board → Settings → Listings, the "Default currency" field). Multi-currency boards still display each job in its own currency, but the filter applies the comparison after a normalized conversion.

REST equivalent

If you're driving listings programmatically:

GET /wp-json/wcb/v1/jobs?salary_min=60000&salary_max=120000

Both bounds are optional. Omit salary_max for "$60k+" listings; omit salary_min for "up to $120k" listings.

On mobile

The slider stacks below the search bar and uses a touch-friendly grip. The chip pill remains tap-to-clear.

Apply as a Guest

You can now apply to a job without creating an account first. The apply form on every job page accepts:

  • Your name + email
  • A cover letter (optional)
  • A resume file upload (PDF / DOC / DOCX)

This makes it easy to apply on the spot - no signup wall.

How to apply as a guest

  1. Open any job page (e.g. /jobs/senior-backend-engineer/).
  2. Click Apply Now.
  3. The apply panel opens - fill in your name + email.
  4. Drop a resume file into the Click to upload resume zone, or pick one with the file picker. PDF, DOC, and DOCX accepted, up to the size cap configured by the site (default 5 MB, sites can raise to 20 MB).
  5. (Optional) Write a cover letter in the Cover Letter (optional) textarea.
  6. Click Submit Application.

The employer receives the application instantly. They see your name, email, cover letter, and resume preview from their dashboard.

Required vs optional resume

Whether a resume is required depends on the site's settings:

  • Resume required (the default for new sites) - you must attach a file to submit.
  • Resume optional - you can submit without a file. The employer may follow up via email.

If a site requires a resume but you try to submit without one, you'll see a clear error message: "A resume is required to apply for this job." Drop a file and resubmit.

Privacy

Your application is stored against your email address. If you later create an account using the same email, the system will link your historical guest applications to the new account automatically - your "My Applications" page will show them.

This linking happens automatically the moment your account is created (1.7.0) - there's nothing to request or claim manually. Just register with the same email address you applied with, and every guest application on file for that email becomes part of your application history.

If you'd like a copy of your data or want it deleted, the Privacy & My Data controls in the candidate dashboard handle GDPR self-service requests.

File format support

Format Accepted Note
PDF Yes Recommended - preserves layout for the employer
DOC Yes Older Word format
DOCX Yes Modern Word format
ODT, RTF, TXT No Not currently supported. Save as PDF first.
Image (JPG / PNG) No Photos of resumes are rejected - convert to PDF

What happens after submit

You'll see a confirmation message inline: "Application submitted - the employer will be in touch." That's it. No further account-creation steps unless you want to track applications going forward.

Troubleshooting (Candidates)

Common things candidates run into, with the practical fix for each. If you're an employer, see for-employers/12-troubleshooting.md.

"I applied but never heard anything back"

That's almost always normal - most employers review applications in batches. Check Candidate Dashboard → My Applications to verify your application is there.

  • Status "Submitted" - the employer has it, hasn't acted yet. No action from you needed.
  • Status "Reviewing" - they've looked at it.
  • Status "Shortlisted" - you're under consideration. Expect follow-up.
  • Status "Hired" - congratulations, you got the job.
  • Status "Rejected" - not a fit for this role; the application is closed.
  • Status "Withdrawn" - you (or the system) withdrew it.
  • Status "Job Removed" - the job posting was taken down. Your application is preserved in your history but no further action is expected.

If you don't see the application at all in your dashboard, it didn't submit successfully - try again.

"The Apply button is missing from a job"

A few reasons this happens:

  1. The job's deadline has passed. Expired jobs hide the apply button. Look for the deadline date on the job page.
  2. The job was filled or unpublished. If the employer closed the posting, the apply button is removed.
  3. The site requires the Candidate role. Most sites let any logged-in member apply, but some turn on "Require Candidate Role" - on those, register or sign in with a candidate account first.

You usually do not need an account at all: most sites also allow guest applications. See Apply as a Guest.

"I can't apply - it says 'You have already applied'"

You already submitted to this job. Two ways this happens:

  • You applied as a guest with the same email. The system blocks duplicate guest applications to the same job within 24 hours. If you really want to send a different application, register an account and apply from there.
  • You applied as a logged-in candidate. Each candidate can apply once. Withdraw the existing application (from your dashboard) if you want to re-apply with a different resume.

"My resume upload failed"

  • File too large. The default limit is 5 MB. The site admin can raise it up to 20 MB, but if your file is over the limit you'll see "File must be under X MB." Re-export your PDF with smaller image embeds.
  • Wrong format. Only PDF, DOC, and DOCX are accepted. ODT, RTF, TXT, and images are rejected - convert to PDF first.
  • Network blip. Re-try the upload. Don't hit "Apply" again until the upload completes.

"I can't find a job I saw earlier"

  • It might have expired. Default listing hides past-deadline jobs. Use the search bar to find it by title - expired jobs may still be searchable in some configurations.
  • It might have been deleted. If the employer pulled the posting, it's gone.
  • You bookmarked it. Check Candidate Dashboard → Saved Jobs - bookmarks survive even if the job changes status.

"My saved jobs aren't showing up"

  • Make sure you're logged in. Bookmarks are tied to your account; they don't survive logout if you're using a guest session.
  • The bookmark might not have saved. Try clicking the bookmark button again. The button highlights when the job is saved.

"I didn't get the confirmation email after applying"

  • Check your spam / promotions folder. Most missing emails are spam-flagged.
  • The site might have email-sending issues. This is a site-admin problem, not yours - your application IS still recorded (verify in your dashboard).
  • Wrong email on file. If you applied as a guest with a typo in your email, the confirmation went to the wrong address. The application is recorded but you have no way to track it. Register an account and apply again with the right email.

"I see 'Job no longer available' on one of my applications"

The employer (or a site admin) deleted that job posting after you applied. Your application is preserved in your history - that's intentional, so you have a record of having applied. The status moves to "Job Removed" so you know it's no longer in flight.

If you'd been hired or shortlisted before the deletion, the employer typically reaches out separately. If you weren't yet, the role won't move forward through this posting - they may re-post later, or they may have filled it through another channel.

"I'm getting too many job alerts (or too few)"

  • Manage your alerts at Candidate Dashboard → Job Alerts. Each alert has saved search filters and a frequency you can edit or delete.
  • Email frequency is per-alert: Instant, Daily, or Weekly. If you set up multiple alerts with overlapping filters, you'll get multiple emails - consolidate them or lower the frequency.

"Employers aren't finding my profile"

Employers browse candidates through the Find Candidates archive. Your profile is Public by default, so it appears there as soon as you have an account. (Profiles can be made Private, in which case only you and admins can see them - that switch is API-driven and is exposed in WP Career Board Pro.) To improve your discoverability:

  • Complete your profile. Open Candidate Dashboard -> Profile and add a bio, phone, and location. Empty profiles are easy to skip past.
  • Keep your account details current under Candidate Dashboard -> Account Settings (display name and email).
  • Build a resume. With WP Career Board Pro, use the Resume Builder so employers see your structured experience and education, and can download a PDF.

Some themes (for example BuddyX Pro) also show an "#OpenToWork" badge on member profiles. That badge is a theme integration and is separate from the Find Candidates archive.

"I forgot my password"

Use the standard WordPress "Lost password" link on the login page. You'll get a reset email at the address you registered with.

If you are already signed in and just want to change your password, use Candidate Dashboard → Account Settings → Change Password instead.

"I want to delete my account"

Go to Candidate Dashboard → Account Settings → Privacy & My Data and click Request account deletion. This sends a confirmation email to your registered address. After you click the link in that email, the site administrator processes the erasure, which permanently removes:

  • Your account
  • All your applications (employers see "Anonymous candidate" on archived applications, not your details)
  • Your resume(s)
  • Your saved jobs, saved companies, and alerts

This is a GDPR / privacy compliant erasure and cannot be undone. The same panel also has Request data export if you just want a copy of your data.

I'm stuck - who do I contact?

Look on the site for a "Contact" link, usually in the footer. When you reach out, include:

  1. The URL of the page where the problem happens.
  2. A screenshot of what you see.
  3. The time and date.
  4. The email address tied to your account.

Don't include passwords, payment info, or sensitive personal data - just descriptive details.

Profile, Account & Notifications

Beyond applications and saved jobs, the Candidate Dashboard gives you three account-management tabs: Profile, Account Settings, and (when the site enables the notification bell) Notifications. They are part of the same Candidate Dashboard block (shortcode [wcb_candidate_dashboard]).

Profile

Open the Profile tab to control how you appear to employers in the Find Candidates archive. Your profile is Public by default, so it is visible there as soon as you have an account.

The Profile tab lets you edit:

Field Notes
Email Read-only here. Change it from Account Settings (below).
Phone Optional contact number shown on your profile and resume.
Location City and country, e.g. "Bengaluru, India".
Bio / About Me A short rich-text introduction for employers.

If the site runs add-ons or WP Career Board Pro's Field Builder, extra custom fields can appear on this tab as well. Click Save Profile to store your changes; a "Saved" confirmation appears when it succeeds.

Account Settings

Open the Account Settings tab for the parts of your account tied to login, not to your public profile.

Account details

  • Display Name - the name shown across the site.
  • Email - your login and notification address. Editable here.

Click Save changes to apply.

Change Password

A dedicated panel lets you change your password without leaving the dashboard:

  1. Enter your Current Password.
  2. Enter and confirm a New Password.
  3. Click Update password.

If you are locked out instead, use the WordPress "Lost password" link on the login page.

Privacy & My Data (GDPR self-service)

The same tab includes a Privacy & My Data panel with two self-service controls:

  • Request data export - asks the site to compile a copy of your personal data. You receive an email when it is ready.
  • Request account deletion - sends a confirmation email; after you click the link, the site administrator permanently deletes your account, applications, resume(s), saved jobs, saved companies, and alerts. This cannot be undone.

Both requests are processed by the site administrator, and you are emailed when each one completes.

Delete your account from the app

New in 1.7.0 - if the site offers the WP Career Board companion mobile app, you can delete your own account directly from the app, without waiting on the site administrator. Confirm your password and type DELETE to confirm, and the deletion is scheduled with a grace period (14 days by default): your account is locked for that window, but signing back in before the grace period ends cancels the deletion and restores full access. Once the grace period passes, your account is permanently removed - same underlying WordPress account-deletion cascade as the site administrator's tools use, so it's the same kind of erasure described above under Privacy & My Data.

Notifications

When the site owner enables the in-dashboard notification bell, a Notifications tab appears with an unread badge. It lists your Career Board notifications (for example application status changes) inside the dashboard, so you don't have to rely on email alone.

The Notifications tab and the bell are provided by WP Career Board Pro. On Free-only installs you still receive email notifications, but the in-dashboard Notifications tab is not shown.

Admin Guide

Site-owner configuration: settings, moderation, email, GDPR, custom fields.

Settings

Configure WP Career Board from WP Career Board → Settings in wp-admin. Settings are organized into tabs.

Settings Page - Job Listings Tab

Job Listings Tab

Controls how jobs behave on your board.

Setting Default Description
Auto-Publish Jobs Off When on, submitted jobs go live immediately without admin approval
Jobs Per Page 10 Number of jobs shown per page in the listings grid (1-100)
Job Expiry (days) 30 Jobs auto-close after this many days (1-365). Closing is reversible - open the job in admin and republish to extend its lifetime
Deadline Auto-Close Off Automatically closes jobs when their application deadline passes
Allow Withdraw On Lets candidates withdraw their own applications. Turn off for apply-once-final flows (compliance, regulated hiring)
Default Salary Currency USD Site-wide default currency for new job postings; employers can override per job
Resume Required On Require applicants to attach a resume on the apply form
Application Resume File Size (MB) (host default) Maximum size for an uploaded resume file
Featured Duration (days) 30 How many days a job stays in the Featured spotlight before reverting automatically (1-365). See Featured Listing Expiry
Require Candidate Role Off Off lets any logged-in member apply and manage a resume (ideal for community sites). Turn on to reserve the candidate experience for users with the Candidate role

Pages Tab

Links each feature to its dedicated page. If the Setup Wizard ran successfully, these are filled in automatically.

Setting Purpose
Jobs Archive Page The main job board browse page (Find Jobs)
Employer Dashboard Page The employer's management page
Candidate Dashboard Page The candidate's tracking page
Company Archive Page The public company directory
Post a Job Page The standalone job-submission page
Employer Registration Page The employer sign-up page
Resume Archive Page The resume directory (used when WP Career Board Pro is active)

If a page assignment is blank, the related functionality (e.g., "View your dashboard" links in emails) won't work correctly. Always fill these in.

Notifications Tab

Controls the sender name, from email, and admin notification email address used by all WCB emails. See Email Notifications for the full guide.

Emails Tab

Lets you enable or disable each individual email notification and customize its subject line and body. See Email Notifications for placeholders and customization options.

Import Tab

One-click migration from WP Job Manager. See Import & Migration for the full guide.

Anti-Spam Tab

A honeypot field protects every submission form automatically (no setup, no performance cost). For a stronger second layer, choose a CAPTCHA provider:

  • None - honeypot only (default).
  • Cloudflare Turnstile - enter the Turnstile Site Key and Secret Key.
  • Google reCAPTCHA v3 - enter the reCAPTCHA Site Key, Secret Key, and an optional score threshold (default 0.5).

The chosen provider guards both the job-submission and job-application forms.

Pro-Only Tabs

When WP Career Board Pro is active, seven additional tabs appear:

Tab What It Controls
Resumes Resume visibility, file upload, and resume builder settings
Boards Multi-board engine: create and manage independent job boards; pipeline stages are configured within this tab
Field Builder Custom fields for jobs, companies, and candidates
Credits Credit settings, product-to-credit mappings, detected payment providers, and credits-per-job-post value
AI Settings Configures the AI provider key for AI Chat Search and job description generation
Job Feed RSS/JSON feed settings for job listing aggregators
Integrations Third-party service connections and API integrations
License Pro license key activation and management

Saving Settings

Click Save Changes at the bottom of any tab. Settings are saved per-tab - you don't need to switch tabs before saving.

Email Notifications

WP Career Board sends automatic emails for key events. All emails use WordPress's built-in wp_mail() function and are fully customizable.

Email Notifications Settings

Notification Events

Email Sent To Trigger
New Job Pending Review Admin Employer submits a new job
Job Approved Employer Admin approves a pending job
Job Rejected Employer Admin rejects a pending job
Job Expired Employer Job reaches its expiry date
Application Received Employer Candidate applies to their job
Application Confirmation (Candidate) Candidate Registered candidate submits an application
Application Confirmation (Guest) Guest Guest applicant submits an application
Application Status Changed Candidate Employer updates application status (Reviewing, Shortlisted, Rejected, Hired)

Managing Notifications

Go to WP Career Board → Settings → Emails.

Each notification can be:

  • Enabled or disabled - toggle the switch to turn it on or off
  • Customized - edit the email subject and body text

Click the email name to expand the editor for that notification.

Editable body per template

Every notification ships with a ready-to-use default body, and since 1.6.0 that body is fully editable per template from this screen. Leave the body field blank to send the shipped default, or type your own text to override it - a Load default button next to the field loads the shipped wording back in as a starting point if you want to edit from there instead of writing from scratch. If a template's body is left empty, the email still sends with its sensible default rather than going out blank.

Send Test Email

Each template ships with a Send test button on the right of the row. Clicking it dispatches a one-shot copy of that email to the admin user's address with sample merge-tag values, so you can preview the rendered template before any real applicant sees it.

Send test email button in the Sent state

The button works for both enabled and disabled templates - disabled templates are still rendered and dispatched for preview, but their log rows are tagged sent_test in the activity log so admin previews stay separate from production delivery metrics. A green check + "Sent" label appears for 2.5 seconds after a successful dispatch, then resets.

If the button shows "Failed", check:

  • An SMTP plugin is configured (the local dev mail handler often fails silently)
  • The admin user has a valid email address on their profile
  • The Email Activity Log row says sent_test for the most recent attempt - if the row is missing, see the self-heal note below

Email Placeholders

Use these placeholders in email subjects and bodies - they are replaced with real values when the email sends:

Placeholder Value
{job_title} The job listing title
{company_name} The employer's company name
{candidate_name} The applicant's full name
{application_status} Current status of the application
{dashboard_url} Link to the employer or candidate dashboard
{job_url} Link to the job listing page
{site_name} Your WordPress site name

Email From Name and Address

Go to WP Career Board → Settings → Notifications to set:

  • From Name - the sender name shown in inboxes (e.g. "Career Board")
  • From Email - the reply-to address for all WCB emails
  • Admin Notification Email - where admin alerts (e.g. new job pending review) are sent

SMTP / Deliverability

For reliable email delivery, use an SMTP plugin (WP Mail SMTP, FluentSMTP, or similar). WordPress's built-in mail function can land in spam without SMTP configuration.

Email Activity Log

Every dispatched email writes a row to wp_wcb_notifications_log and surfaces on the Activity Log tab at the bottom of Settings → Emails. Rows show the event type, channel, recipient, status (sent / failed / sent_test / failed_test), and timestamp.

The log table is created on plugin activation. If for any reason the table is missing (e.g. a database migration dropped it, or the plugin was installed pre-1.0.x and skipped the activation routine), the dispatch path self-heals the table on first send rather than failing silently - your previously missing log entries will start populating from the next dispatch onward.


Pro Email Notifications (Pro)

WP Career Board Pro extends the email system with three additional transactional emails. You can customise the subject line and enable or disable each one from Career Board -> Settings -> Emails.

Job Alert Digest

  • Recipient: Candidate
  • Trigger: Fired when the Job Alerts module finds new jobs matching a candidate's saved search
  • Content: A list of matching job titles with direct links

Credit Top-Up Confirmation

  • Recipient: Employer
  • Trigger: When a credit purchase completes via a supported payment gateway (WooCommerce, Paid Memberships Pro, or MemberPress)
  • Content: Confirmation of the purchase and updated balance

Low Credit Balance Warning

  • Recipient: Employer
  • Trigger: Fired when an employer's credit balance reaches zero
  • Content: Balance warning and a link to the Employer Dashboard to purchase more credits

Email Template Customisation

All Pro emails use the same templating system as Free emails. To override a template, copy the relevant file into your theme's wp-career-board/emails/ folder (the same override location Free uses), or register a custom template directory with the wcb_email_template_dirs filter.

In-App Notification Bell (Pro)

The notification bell appears in the Employer Dashboard and Candidate Dashboard. It shows a live unread count and drops down to display a list of recent notifications, each with a message and a link to the relevant page.

Events That Trigger Bell Notifications

Event Who Receives It Message Example
Application submitted Employer "Jane Doe applied for Senior PHP Developer"
Application submitted Candidate "Your application for Senior PHP Developer was submitted"
Application status changed Candidate "Your application for Senior PHP Developer is now Shortlisted"
Job approved Employer "Your job 'Senior PHP Developer' has been approved"
Job rejected Employer "Your job 'Senior PHP Developer' was not approved"
Job expired Employer "Your job 'Senior PHP Developer' has expired"

All notifications are stored in the wcb_notifications database table. The is_read flag is set to 0 on insert. The bell badge count reflects the number of unread rows for the current user.

Deadline reminders

New in 1.1.0 - candidates who saved a job but haven't applied get automated reminders before the application deadline closes.

Reminder schedule

When Email
3 days before the deadline "Your saved job is closing soon" reminder
1 day before the deadline "Last chance to apply" final reminder

Both reminders are skipped if:

  • The candidate has already submitted an application for that job, OR
  • The candidate has un-saved the job, OR
  • The job has been closed / removed before the cron fires.

Cron event

Registered as wcb_send_deadline_reminders, runs daily.

WordPress's wp-cron triggers it on the next page load after the scheduled time - for low-traffic sites, install a real cron job that hits wp-cron.php to keep timing accurate.

To trigger manually:

wp cron event run wcb_send_deadline_reminders

Disabling deadline reminders

The deadline reminder is one of the email templates on the Career Board → Settings → Emails tab. Toggle its Enabled switch off to stop the reminders. The cron stays scheduled (so re-enabling is one click) but the disabled template is not dispatched.

Toggling the template off is the supported way to stop the reminders and is all most sites need.

To stop the cron entirely as well (for example, on a staging environment), unschedule the event with WP-CLI:

wp cron event delete wcb_send_deadline_reminders

Or unschedule it in code:

$timestamp = wp_next_scheduled( 'wcb_send_deadline_reminders' );
if ( $timestamp ) {
    wp_unschedule_event( $timestamp, 'wcb_send_deadline_reminders' );
}

The plugin re-schedules the event on the next page load, so deleting it is mainly useful when the plugin is also being deactivated.

Email template

Standard plugin email format with the configured logo, header/footer. Subject line: "Your saved job '{{job_title}}' closes in {{days}} days".

Custom merge tags available:

Tag Value
{{candidate_name}} Candidate first name
{{job_title}} Title of the saved job
{{company_name}} Company that posted the job
{{deadline_date}} Localized deadline date
{{days}} Days until deadline
{{job_url}} Direct link to the job page

Override the template by copying modules/notifications/templates/emails/deadline-reminder.php into your theme's wp-career-board/emails/ folder.

Moderation

Moderation controls whether jobs need admin approval before they go live. It prevents spam and low-quality listings on your board.

How Moderation Works

When Auto-Publish Jobs is turned off (the default), every job submitted by an employer goes to a Pending state and must be approved by an admin before it appears on the job board.

When Auto-Publish Jobs is turned on, submitted jobs go live immediately without review.

To toggle moderation: WP Career Board → Settings → Job Listings → Auto-Publish Jobs

Reviewing Pending Jobs

  1. Go to WP Career Board → Jobs in wp-admin
  2. Click the Pending filter at the top of the list
  3. Click any job title to open the full edit screen and review the content

Admin Jobs - Pending Filter

Approving a Job

Quick approval (from the list):

  1. Hover over the job in the list
  2. Click Approve under the title

Full review (from the edit screen):

  1. Open the job in the wp-admin editor
  2. Review all details
  3. Change the status to Published in the Post Status panel
  4. Click Update

When a job is approved, the employer receives an email notification.

Rejecting a Job

  1. Open the job in the wp-admin editor
  2. Change the status to Draft or Trash
  3. Optionally email the employer with a reason (done manually outside the plugin)

Managing Existing Jobs

Admins have full control over all jobs from WP Career Board → Jobs:

  • Edit any job (correct errors, add missing info)
  • Close a job that is running too long
  • Delete spam or low-quality listings

Reported Jobs (Flagged)

Any logged-in user can report a published job from its single page ("Report this job", with a reason). Reports are stored on the job and deduplicated per user, so one person reporting the same job repeatedly counts once.

Moderators and admins review reports from WP Career Board → Jobs:

  1. Click the Flagged view at the top of the list (it appears, with a count, only when one or more jobs have open report flags).
  2. The Flags column shows how many open reports each job has.
  3. Resolve a flagged job with the row or bulk actions (the row action is Dismiss flag; the bulk action is Dismiss flags):
    • Dismiss flag(s) - clears the open reports and leaves the job published (the report was not actionable).
    • Unpublish - takes the job down and clears its reports.

Resolving flags requires the Moderate Jobs capability (wcb_moderate_jobs), the same gate as approving and rejecting jobs.

Member Moderation (Reporting, Blocking, Suspending)

New in 1.7.0 - moderation now covers members, not just job listings. This layer is separate from Reported Jobs above: it deals with a member's account and behaviour, not a single listing.

Members reporting members

Any logged-in member can report another member's profile for a reason such as spam, scam, a fake profile, harassment, or offensive content. Reports are deduplicated per reporter (reporting the same member twice counts once) and accumulate on the reported member's account.

Open reports surface to admins as a warning badge (with the report count) on the Career Board → Candidates screen, next to that member's Active/Suspended status.

Members blocking members

Any logged-in member can block another member directly from their account. Blocking is mutual: once either side blocks the other, neither one sees the other's job listings or single job pages - enforced server-side on both the REST API and the server-rendered frontend, not just hidden in the browser. A member can review and undo their own blocks from their blocked-members list in the app.

Site owners suspending candidates

Admins and moderators can suspend a candidate account directly from Career Board → Candidates:

  1. Go to Career Board → Candidates.
  2. Hover a candidate's row and click Suspend (or select multiple rows and choose Suspend from the Bulk Actions dropdown).
  3. A suspended candidate loses every Career Board ability immediately
    • applying, saving jobs, and any other write action - including from a mobile client using an Application Password.

Click Restore (or the Restore bulk action) to lift the suspension. This uses the same suspend/restore mechanism already used for employers on the Career Board → Employers screen.

Admin Notifications

Admins receive a New Job Pending Review email when an employer submits a job for approval. This is the only admin-facing email notification. Notification content can be customized in Settings → Emails.

GDPR & Privacy

WP Career Board integrates with WordPress's built-in privacy tools to help you comply with GDPR and similar data protection regulations.

What Data WP Career Board Stores

Per employer:

  • Company name, logo, description, website, size, industry
  • Posted job listings

Per candidate:

  • Name and email address
  • Cover letters submitted
  • Application history and status

System logs:

  • Application timestamps

Data Export

WordPress has a built-in personal data export tool. WP Career Board integrates with it so all job board data for a user is included.

To export a user's data:

  1. Go to Tools → Export Personal Data in wp-admin
  2. Enter the user's email address
  3. Click Send Request
  4. The user receives an email with a link to download their data export

The export includes all applications, cover letters, and profile data associated with that email address.

Data Erasure

To erase a user's personal data:

  1. Go to Tools → Erase Personal Data in wp-admin
  2. Enter the user's email address
  3. Click Send Request
  4. The user confirms via email
  5. After confirmation, WordPress erases all personal data including WP Career Board records

Note: Erasing a user's data removes their applications and profile. Job listings posted by an employer are not automatically deleted - you may need to manually remove those.

Privacy Policy Page

Add the following to your privacy policy to inform users what data WP Career Board collects:

  • Account registration data (name, email)
  • Job applications including cover letters
  • Activity logs for job board interactions
  • No payment data is stored (payments are processed by your e-commerce plugin - WooCommerce, PMPro, or MemberPress - not by WP Career Board directly)

WP Career Board does not set any cookies in the free version. Session state (e.g., active dashboard tab) is stored in sessionStorage (browser memory only, not a cookie, cleared when the browser tab closes).

Custom Field Builder

Pro feature - Requires WP Career Board Pro.

The Field Builder lets you add custom fields to job listings, company profiles, and candidate profiles - no code required. Fields appear automatically in the relevant forms and public pages.

Field Builder - Admin Interface

What You Can Add

  • Fields to job listings - e.g., Remote Policy, Visa Sponsorship, Tech Stack
  • Fields to company profiles - e.g., Funding Stage, Team Size, Benefits
  • Fields to candidate profiles - e.g., Notice Period, Preferred Work Style, Portfolio URL

Accessing the Field Builder

Go to Career Board → Settings → Field Builder in wp-admin.

You will see three tabs:

  • Job Fields - fields added to job listings
  • Company Fields - fields added to company profiles
  • Candidate Fields - fields added to candidate profiles

Creating a Field Group

Fields are organized into groups - collapsible sections with a label (e.g., "Compensation Details").

  1. Click Add Group
  2. Enter a group label
  3. Click Save Group

You can create multiple groups to organize related fields.

Adding a Field

  1. Expand the group where you want to add the field
  2. Click + Add Field
  3. Configure the field:
Setting Description
Field Label The label shown on the form and public page
Field Type Text, Textarea, Number, Select, Checkbox, Date, URL, File Upload
Required Whether the field must be filled in
Visibility Public, Logged In Only, Employer Only, Candidate Only
Placeholder Hint text shown inside the input
Options The choices available (for Select and Checkbox fields)
  1. Click Save Field

Adding a Custom Field

Field Types

Type Use for
Text Short values - tech stack, notice period, LinkedIn URL
Textarea Longer text - benefits overview, culture note
Number Salary, team size, years of experience
Select Single-choice dropdown - Remote Policy, Visa Sponsorship
Checkbox Group Multiple choices - Benefits, required skills
Toggle Single on/off - "Visa sponsorship available?"
Date Application deadline, estimated start date
URL Portfolio, GitHub, external job link
File Upload Attach a PDF, document, or image

Visibility Rules

Each field can be set to:

  • Public - visible to all visitors including guests
  • Logged in only - visible to registered users only
  • Employer only - visible only to employers (e.g., on the job form)
  • Candidate only - visible only to candidates

Reordering

Drag and drop fields within a group to reorder them. Drag and drop groups to change their order. Changes save automatically.

Deleting a Field

Click Delete on any field. This permanently removes the field and all stored values across all posts. This cannot be undone.

Where Fields Appear

Field Type Appears in Displayed on
Job Fields Multi-step Job Form Job single page
Company Fields Company Profile editor Public company page
Candidate Fields Candidate profile settings Candidate profile

Import & Migration

WP Career Board includes a built-in migration tool to import jobs and resumes from WP Job Manager. Access it from WP Career Board → Settings → Import.

Import Page

Overview

The importer reads data from WP Job Manager's post types (job_listing, resume) and creates equivalent WCB records (wcb_job, wcb_resume). Your original WP Job Manager data is never modified or deleted.

The import uses REST API calls (POST /wcb/v1/import/run) batched in groups, with a live progress bar so large imports don't time out.

Idempotent - Safe to Re-Run

Every migration checks for an existing WCB record before importing. Records already imported are automatically skipped. You can run the import multiple times without creating duplicates.

Available Migrations

WP Job Manager → Jobs (Free)

Migrates job_listing posts to wcb_job. Available in the free plugin.

Fields migrated:

WP Job Manager field WCB equivalent
Title & description Job title + post content
_job_location _wcb_location + location taxonomy
_job_salary _wcb_salary_min / _wcb_salary_max
Salary currency & pay type _wcb_salary_currency / _wcb_salary_type
_job_expires / _job_duration _wcb_deadline
_featured _wcb_featured
_remote_position _wcb_remote
_application (email or URL) Preserved as application meta
_company_name, _company_website, _company_tagline, _company_twitter, logo, video Company profile meta
_filled → closed Post status mapped to Closed
job_cat, job_type taxonomies wcb_category, wcb_job_type

How to run:

  1. Go to WP Career Board → Settings → Import
  2. The card shows how many WP Job Manager jobs were found and how many are already imported
  3. Click Import All Jobs
  4. A progress bar shows batch-by-batch progress until complete

WP Job Manager does not need to remain active after the import is complete.

WP Job Manager Resumes → Resumes (Pro)

Pro feature - Requires WP Career Board Pro.

Migrates resume posts to wcb_resume. Only available when WP Career Board Pro is active.

Fields migrated:

WP Job Manager Resumes field WCB equivalent
Candidate name & bio Resume title + summary
Professional title Resume headline
Contact email Candidate email
Location Resume location
Photo Candidate avatar
Video URL Resume video link
Resume file attachment Attached file
_featured Featured flag
_resume_expires Expiry date
Education history Education section entries
Work experience Work Experience section entries
Social / website links Links section entries
resume_category Resume categories

How to run:

  1. Go to WP Career Board → Settings → Import
  2. The WP Job Manager Resumes card is shown when Pro is active
  3. Click Import All Resumes
  4. Monitor the progress bar until complete

What Happens with Duplicates

Each import run checks whether a WCB record already exists for a given WP Job Manager post ID (tracked via the _wcb_migrated_from meta key). If it does, that record is skipped and counted as "already imported" - not re-imported or overwritten.

Progress Display

The Import page shows live stats for each migration:

Stat Meaning
Found Total records in WP Job Manager
Already imported Records already migrated to WCB
Remaining Records that will be processed on the next run

After Importing

  1. Go to WP Career Board → Jobs to review imported jobs - check statuses and verify key fields
  2. Go to WP Career Board → Settings → Pages and confirm page assignments are correct
  3. Flush your permalink structure via Settings → Permalinks → Save Changes
  4. If WP Job Manager had categories or job types that don't map cleanly, review them in WP Career Board → Job Categories and WP Career Board → Job Types

Limitations

  • Custom fields added by WP Job Manager extensions are not automatically mapped - you will need to re-enter those manually
  • Applications submitted in WP Job Manager are not migrated (no equivalent structure in the free plugin)
  • The importer does not delete WP Job Manager data after migration - you can deactivate and delete WP Job Manager separately once you are satisfied with the results

Credit System (Pro)

Pro feature - Requires WP Career Board Pro.

The Credit System lets you charge employers credits to post jobs. Credits are purchased through your existing e-commerce plugin - WooCommerce, Paid Memberships Pro, MemberPress, or WooCommerce Subscriptions - and deducted automatically when jobs go live.

How It Works

  1. Admin creates a product - create a WooCommerce product (or PMPro plan, MemberPress membership) that represents a credit package
  2. Admin maps product to credits - in Settings → Credits, map that product to a credit amount (e.g., "10 Job Posting Credits" product = 10 credits)
  3. Employer buys credits - purchases the product through your shop using any payment gateway (Stripe, PayPal, Square, etc.)
  4. Credits added on purchase - when the order completes, credits are automatically added to the employer's balance
  5. Credits held on submit - when the employer submits a job, the required credits are reserved
  6. Credits deducted on approval - when the job goes live, credits are consumed
  7. Refund on rejection - if the admin rejects a job, held credits are returned

Credit Ledger

Every transaction is logged in an append-only audit trail:

Type Effect
Top-up Credits added (from a purchase or manual adjustment)
Hold Credits reserved (job submitted, awaiting approval)
Deduct Credits consumed (job approved and live)
Refund Credits returned (job rejected or cancelled)

Supported Payment Providers

WP Career Board Pro uses the Wbcom Credits SDK with adapters for each payment provider. The Credits tab automatically detects which plugins are active on your site:

Provider Plugin Required How Credits Are Triggered
WooCommerce WooCommerce (free) Order status changes to "completed"
WooCommerce Subscriptions WooCommerce Subscriptions Credits added on each subscription renewal
Paid Memberships Pro Paid Memberships Pro Credits added when a membership level is activated
MemberPress MemberPress Credits added when a membership transaction completes

You can use any payment gateway supported by your chosen provider - Stripe, PayPal, bank transfer, or anything else the provider supports. WP Career Board does not process payments directly.

Step 1: Create a Credit Product

  1. Go to Products → Add New in wp-admin
  2. Set the product name (e.g., "10 Job Posting Credits")
  3. Set the product type to Simple product
  4. Set a price (e.g., $79.00)
  5. In the product description, explain what the employer gets
  6. Publish the product

Repeat for each credit tier you want to offer:

Product Name Price Credits (mapped in Step 2)
Starter - 3 Credits $29 3
Growth - 10 Credits $79 10
Agency - 25 Credits $149 25

For WooCommerce Subscriptions, create a subscription product instead. Credits will be added on each renewal, giving employers a recurring credit allowance.

Create a membership level that represents a credit tier. When an employer activates that membership level, credits are added based on your mapping in Step 2.

MemberPress

Create a membership that represents a credit tier. When the membership transaction completes, credits are added based on your mapping in Step 2.

Step 2: Map Products to Credits

  1. Go to WP Career Board → Settings → Credits
  2. Under Credit Mappings, click Add Mapping
  3. Select your WooCommerce product (or PMPro level, MemberPress membership) from the dropdown
  4. Enter the number of credits that product should grant
  5. Click Save Changes

Each product can map to a different credit amount. When an employer purchases that product and the order completes, the mapped number of credits is automatically added to their balance.

Step 3: Configure Credit Settings

In WP Career Board → Settings → Credits, configure:

Setting Description
Credits per Job Post How many credits are deducted when a job is approved. Set to 0 for free posting.
Low Balance Alert Threshold When an employer's balance drops to this number, they see a warning.
Credits Purchase URL The URL where employers are sent to buy more credits (typically your WooCommerce shop page or a dedicated credits page).

Detected Providers

The bottom of the Credits tab shows Detected Providers - a list of which payment plugins are currently active. If a provider is not shown, activate its plugin and refresh the page.

Employer Experience

Employers see their credit balance in:

  • The Employer Dashboard header
  • The Confirm & Submit step of the Job Form

When their balance is too low, they see a "Buy Credits" prompt linking to your configured Credits Purchase URL. The employer completes the purchase through your WooCommerce checkout (or PMPro/MemberPress registration) using whatever payment method you have configured.

Employer Dashboard - Credit Balance

The Hold → Deduct → Refund Cycle

  1. Hold - When an employer submits a job, the required credits are immediately reserved from their available balance. The employer cannot spend held credits on another job.
  2. Deduct - When the admin approves the job (or it auto-publishes), the held credits are permanently consumed.
  3. Refund - If the admin rejects the job, the held credits are returned to the employer's available balance.

This ensures employers are never charged for jobs that don't go live.

Admin Credit Adjustment

Admins can manually add or deduct credits for any employer:

  1. Go to WP Career Board → Employers
  2. Click the employer's name
  3. In the Credits section, enter the number of credits to add (or a negative number to deduct)
  4. Add an optional note (e.g., "Trial credits" or "Compensation for rejected job")
  5. Click Adjust Credits

Manual adjustments are recorded in the credit ledger with the admin's note, so there is always a clear audit trail.

Viewing the Credit Ledger

The full transaction history for any employer is visible from their admin profile - every top-up, hold, deduction, refund, and manual adjustment with timestamps and notes.

Troubleshooting & FAQ

Common issues and how to resolve them.


Setup Wizard

The wizard says "Failed to create pages" and won't advance

The wizard calls the WordPress REST API to create pages. This can fail when:

  • Pretty permalinks are off - go to Settings → Permalinks, select any option other than Plain, and save.
  • REST API is blocked - a security plugin, firewall, or hosting rule is blocking /wp-json/. Temporarily deactivate security plugins and try again.
  • Auth cookie not sent - if your site uses basic HTTP auth (common on staging), the REST request won't carry your session. Disable basic auth temporarily or add an exception for /wp-json/.

After fixing the underlying issue, go to WP Career Board → Setup Wizard to run the wizard again.


Pages were created but they're blank or show a 404

The pages were created but may not have the correct block assigned. Edit each page in the block editor and insert the matching block:

Page Block to insert
Find Jobs Job Search + Job Filters + Job Listings
Employer Registration Employer Registration
Employer Dashboard Employer Dashboard
Candidate Dashboard Candidate Dashboard
Companies Company Archive

Then go to Settings → Permalinks and click Save Changes to flush rewrite rules.


Jobs Not Appearing

The Job Listings block shows "No jobs found"

  1. Confirm you have published jobs - go to WP Career Board → Jobs and check the status column.
  2. If jobs are pending review, go to WP Career Board → Settings → Job Listings and check whether Auto-Publish Jobs is enabled. If off, you need to approve each job manually from the Jobs list.
  3. Check your active filters in the block - the Job Type, Category, or Location filters may be set to a value that returns no results.
  4. Go to Settings → Permalinks and click Save Changes to flush rewrite rules.

Jobs appear in wp-admin but not on the frontend

This is almost always a permalink flush issue. Go to Settings → Permalinks and click Save Changes.


Application Form

The "Apply" button does nothing / the application form doesn't open

  • Guest applications are supported by default - no setting needs to be enabled. If the form still doesn't open, check that the user's browser is not blocking JavaScript.
  • If using a page caching plugin (WP Rocket, W3 Total Cache), purge the cache after activating WP Career Board.
  • Check the browser console for JavaScript errors - a JavaScript conflict with another plugin can prevent the form from loading.

Candidates can't submit the application form

  • The job may have a deadline that has already passed. Check the job listing's deadline field.
  • If the job requires a resume upload and the candidate has no resume, the form will block submission. Check if Require Resume is enabled for that job type.
  • Make sure file upload limits in your hosting's php.ini (upload_max_filesize, post_max_size) are large enough for resume files (recommend at least 5 MB).

Email Notifications

Emails are not being sent

WP Career Board uses wp_mail() to send emails. If emails aren't arriving:

  1. Check spam - the notification emails from a local WordPress install often land in spam.
  2. Install an SMTP plugin - the default wp_mail() uses PHP's mail() function, which most shared hosts reject. Install an SMTP plugin (e.g. WP Mail SMTP, FluentSMTP) and connect it to a transactional email service (Mailgun, SendGrid, Postmark).
  3. Verify the sender address - go to WP Career Board → Settings → Notifications and confirm the From email matches your domain. Some hosts reject mail from mismatched domains.
  4. Check notification toggles - each notification type can be enabled or disabled on the Settings → Emails tab. Confirm the relevant notification is enabled.

The wrong email address is receiving notifications

Admin notification emails go to the address set in Settings → Notifications → Admin Email. This defaults to the WordPress admin email but can be overridden.


Employer & Candidate Accounts

A user registered but isn't showing up as an Employer or Candidate

The role is assigned at registration based on which form the user used:

  • Employers register via the Employer Registration page (which contains the Employer Registration block) and get the Employer (wcb_employer) role.
  • Candidates register via the register tab on the Candidate Dashboard page and get the Candidate (wcb_candidate) role.

If a user registered via the standard WordPress registration page, they won't have a job board role. Go to WP Career Board → Employers or Candidates and assign the user, or assign the relevant capabilities with a role manager (#capabilities-and-roles-wcb)).

An employer can't post jobs

  1. Check the employer's account in WP Career Board → Employers - confirm they have the Employer role.
  2. If the Credit System is active (Pro), confirm the employer has available credits. A zero balance blocks job posting.
  3. Confirm the employer can access the Employer Dashboard, where job posting is done.

Credit System (Pro)

Credits were purchased but not added to the employer's balance

Credits are added when the WooCommerce order status changes to "completed" (or the equivalent event for PMPro/MemberPress). If credits are missing after a purchase:

  1. Check order status - go to WooCommerce → Orders and confirm the order is marked "Completed", not "Processing" or "On Hold". Some payment gateways (e.g., bank transfer) leave orders in a non-completed state until manually updated.
  2. Check the credit mapping - go to WP Career Board → Settings → Credits → Credit Mappings and confirm the purchased product is mapped to a credit amount. If the product is not mapped, no credits are granted.
  3. Check Detected Providers - at the bottom of the Credits tab, confirm your payment plugin (WooCommerce, PMPro, or MemberPress) is listed as detected. If it is not shown, activate the plugin and refresh.
  4. Check the debug log - enable WP_DEBUG_LOG in wp-config.php and look for wcb_credits entries in wp-content/debug.log. The Wbcom Credits SDK logs all credit operations.
  5. Manual fix - go to WP Career Board → Employers, click the employer's name, and use Admin Credit Adjustment to manually add the missing credits with a note explaining the reason.

Employer says "Insufficient credits" but they just purchased

The employer's browser may be showing a cached page. Ask them to refresh the Employer Dashboard. If the issue persists, check the order status and credit mapping as described above.


Block Issues

The block editor shows "Your block contains unexpected or invalid content"

This usually means the block's HTML was hand-edited or copied incorrectly. Click Attempt Block Recovery when prompted - this will restore the block from its saved attributes.

The block renders but looks completely unstyled

WP Career Board enqueues its CSS only on pages that contain its blocks. If you are embedding a shortcode or pasting raw HTML outside a block, styles won't load. Use the block editor and insert the correct block instead.


Performance

The jobs page is slow

  • Enable object caching on your server (Redis or Memcached) - WP Career Board caches job queries.
  • If using a page caching plugin, configure it to exclude the Candidate Dashboard and Employer Dashboard pages (they are user-specific and must not be served from cache).
  • The job search uses a live REST API call on every keystroke (with debounce). If the REST API is slow, check for slow database queries using Query Monitor.

Still Stuck?

If none of the above resolves your issue:

  1. Enable WP_DEBUG and WP_DEBUG_LOG in wp-config.php and check wp-content/debug.log for PHP errors.
  2. Deactivate all plugins except WP Career Board to rule out conflicts, then reactivate one by one.
  3. Open a support ticket at wbcomdesigns.com/support with your WordPress version, PHP version, active theme, and a description of what you tried.

Jobs RSS Feed

The plugin exposes a rich RSS feed at /jobs/feed/ containing every published job with full metadata. Wire it up to RSS readers, IFTTT, Zapier, partner aggregators, or your own automation.

Where to find it

https://your-site.com/jobs/feed/

The URL respects whatever post-type slug you've configured (defaults to jobs). If you've changed the slug, the feed URL changes with it.

Item schema

WP Career Board enriches WordPress core's standard job feed: the core template provides <title>, <link>, <description>, <pubDate>, and <guid>, and the plugin injects the wcb:-namespaced fields below into each <item>. The plain-text <description> is also prefixed with a one-line "company - location - salary" summary so readers that ignore custom namespaces still get useful context.

Field Source
<wcb:company> Company name
<wcb:salary currency="..." period="..."> Salary wrapper; carries currency and period attributes and <wcb:min> / <wcb:max> children
<wcb:min> Minimum salary (numeric, no formatting), inside <wcb:salary>
<wcb:max> Maximum salary (numeric, no formatting), inside <wcb:salary>
<wcb:location> Job location term(s)
<wcb:type> Job type term(s) - Full-time, Part-time, Contract, etc.
<wcb:category> Job category term(s)
<wcb:tag> Job tag term(s)
<wcb:experience> Experience-level term(s)
<wcb:deadline> Application deadline - if set
<wcb:apply_url> Direct apply URL, if the employer set an external one
<wcb:apply_email> Direct apply email, if set
<wcb:remote> true or false

Multi-value fields (location, type, category, tag, experience) emit one element per term rather than a comma-joined string.

The wcb: namespace (https://wbcomdesigns.com/xmlns/wcb/1.0/) is declared on the <rss> root so RSS readers that support custom namespaces (most modern ones) can surface these fields.

Filtering the feed

The /jobs/feed/ route is the standard WordPress CPT feed enriched with the wcb: fields above; it does not add custom filter parameters of its own. For a filtered feed, use a taxonomy archive feed, which WordPress generates automatically from the registered WCB taxonomy query vars:

/jobs/feed/?wcb_category=engineering    # one category
/jobs/feed/?wcb_job_type=full-time      # one job type
/jobs/feed/?wcb_location=remote         # one location term

For richer filtering (salary range, remote flag, board, combined filters), use the REST endpoint described under Cache + performance below, which accepts the full job-query surface.

Use cases

  • Cross-post to a Slack channel via Zapier or RSS-to-Slack integration when new jobs are published.
  • Job aggregator listings - many aggregators accept RSS as their ingestion format (Indeed, ZipRecruiter, Google Jobs feeds).
  • Email digest - feed an RSS-to-email tool (Mailchimp, ConvertKit) to send weekly digests.
  • Static site builder - feed Astro / Next.js / Hugo with the feed during build to render a careers page on a marketing site.
  • IFTTT / make.com - trigger downstream automations on new jobs.

Cache + performance

The feed respects WordPress's standard feed caching. WP_DEBUG-disabled production sites cache the feed output for ~5 minutes by default. Tools like WP Super Cache and W3 Total Cache also cache feeds.

If you need a real-time feed for a specific integration, hit the REST endpoint directly:

GET /wp-json/wcb/v1/jobs?per_page=20&orderby=date&order=DESC

The REST API returns JSON with the same data but without RSS-format overhead.

Multilingual: WPML / Polylang

WP Career Board ships with WPML and Polylang configuration files out of the box, so multilingual sites can translate job board CPTs, taxonomies, and key strings without manual setup.

What's translatable

Object WPML Polylang
wcb_job (Jobs) Yes Yes
wcb_application (Applications) Yes - but typically copied per-language to keep the original applicant context Yes
wcb_resume (Resumes) Yes Yes
wcb_company (Companies) Yes Yes
wcb_board (Boards) Yes Yes
wcb_credit_package (Pro only) Yes Yes
Taxonomies (wcb_category, wcb_job_type, wcb_location, wcb_experience, wcb_tag) Yes Yes
Plugin admin strings Yes, via .po / .mo Yes, via .po / .mo
Block attributes (e.g. heading text on Job Listings block) Yes Yes

WPML setup

WP Career Board ships a wpml-config.xml at the plugin root. Activating WPML on a site that already has the plugin active picks up the config automatically.

To verify:

  1. WPML → Translation Management - Jobs, Applications, Resumes, Companies, and Boards should all appear in the post-type selector.
  2. WPML → Settings → Custom Posts - each WCB post type should be set to "Translatable - only show translated items".
  3. WPML → Taxonomy Translation - all 5 WCB taxonomies should be listed and translatable.

Polylang setup

Polylang reads the same wpml-config.xml as WPML (the format is shared between the two plugins for cross-compatibility).

To verify:

  1. Languages → Settings → Custom post types and Taxonomies - tick the WCB post types and taxonomies under "Activate languages and translations management for".
  2. Save.

The plugin then exposes the standard Polylang language switcher in the admin list tables and front-end blocks.

Front-end behavior

Job listings, the Find Jobs page, and the Apply form all respect the current request language:

  • A user browsing the site in fr_FR sees only French jobs in the listings (or all jobs if "Display all languages" is on in WPML / Polylang settings).
  • The Apply form labels, validation messages, and confirmation message render in the request language.
  • REST API endpoints such as GET /wcb/v1/jobs return language-scoped results automatically, because WPML and Polylang filter the underlying WP_Query for the active request language - there is no separate lang query parameter to pass.

Translating plugin strings

The plugin's source .pot file lives at languages/wp-career-board.pot. Translators can:

  • Drop a translated .po / .mo pair under wp-content/languages/plugins/ (override location).
  • OR use Loco Translate, WPML's String Translation, or Polylang's String Translation interface to translate inline.

Currency & locale formatting

Salary formatting respects the site locale:

  • en_US$60,000-$120,000/yr
  • fr_FR60 000 €-120 000 €/an
  • de_DE60.000 €-120.000 €/Jahr

Date formatting (job posted dates, application dates) follows WordPress's date_format + time_format site settings, localized per language.

Known limitations

  • Custom field schema - fields registered via wcb_job_form_fields are translatable using WPML's String Translation, but Polylang requires manual translation entries.
  • Email templates - the email body is sent in the recipient's user-locale (set on each user's profile). Sites without per-user locales fall back to the site default.
  • AI features (Pro) - embeddings + AI matching work language-agnostically, but the UI strings respect the request language.

REST Meta Filters

The GET /wcb/v1/jobs REST endpoint accepts postmeta filters via ?meta_<key>=<value>. The Job Listings block exposes the same surface through its metaFilter attribute.

Default-allow rule (1.2.0+)

Any meta key in the _wcb_* namespace is allowed by default. The plugin owns that prefix, so there is no probe risk for fields like _wcb_visa_sponsorship, _wcb_seniority_score, _wcb_department, etc. Drop the block in the editor or hit the REST endpoint directly without any PHP setup:

GET /wp-json/wcb/v1/jobs?meta__wcb_visa_sponsorship=1
GET /wp-json/wcb/v1/jobs?meta__wcb_department=engineering
[wcb_job_listings metaFilter="_wcb_visa_sponsorship:1"]
[wcb_job_listings metaFilter="_wcb_department:engineering"]

Custom (non-WCB) meta still needs opt-in

Custom or third-party meta keys - anything that doesn't start with _wcb_ - still need to be added to the wcb_jobs_allowed_meta_filters filter before they can be queried. This prevents anonymous probes against arbitrary site-internal postmeta (e.g. a private membership flag set by another plugin):

add_filter( 'wcb_jobs_allowed_meta_filters', function( $keys ) {
    $keys[] = 'partner_company_id';       // not _wcb_*, must opt in
    $keys[] = 'crm_sync_state';           // same
    return $keys;
} );

Then anonymous callers can hit:

GET /wp-json/wcb/v1/jobs?meta_partner_company_id=42

Why this split?

Without any allowlist, any caller could query against any postmeta - including private fields the plugin or other plugins use for internal bookkeeping (e.g. _wcb_employer_banned, _wcb_pending_review_token, or a membership plugin's _member_level field). The pre-1.2.0 behavior required allowlisting every key, which made the common case (filter jobs by a _wcb_* field set by the plugin itself) require PHP. The 1.2.0 split allows the namespace WCB owns while still gating foreign meta.

Block + shortcode integration

The Job Listings block exposes a metaFilter attribute on every shipped surface - Gutenberg inserter, shortcode wrapper, and page-builder embeds:

metaFilter attribute in the block inspector

If you reference a key that's NOT in the _wcb_* namespace and NOT on the explicit allowlist, the block falls back to showing all jobs (no error, but the filter is silently ignored) and a _doing_it_wrong notice fires in WP_DEBUG mode telling you which filter to register.

Matching behavior

Each meta_<key>=<value> filter adds one exact-match meta_query clause (key + value). There is no special _min / _max suffix or comma-list expansion - the value you pass is matched verbatim against the stored postmeta. The dedicated salary range is handled by the separate ?salary_min= / ?salary_max= query parameters, not by the meta-filter surface.

Common patterns

Boolean meta

$keys[] = '_wcb_visa_sponsorship';
$keys[] = '_wcb_relocation_offered';
$keys[] = '_wcb_remote_friendly';

These three are already in the _wcb_* namespace, so they work without any allowlist registration. On the front end:

?meta__wcb_visa_sponsorship=1
?meta__wcb_relocation_offered=1

Register a key with wcb_jobs_allowed_meta_filters only when it is NOT in the _wcb_* namespace (a third-party key like partner_company_id).

Single-value meta

?meta__wcb_department=engineering

Returns jobs whose _wcb_department postmeta equals engineering exactly.

Performance notes

  • All meta filters are added to the WP_Query meta_query array. WordPress core handles indexing.
  • For high-traffic boards, add an index on the relevant rows in wp_postmeta:
    ALTER TABLE wp_postmeta ADD INDEX wcb_meta_visa (meta_key, meta_value(20));
    
  • The jobs REST endpoint caches each query result (keyed by the query arguments) in a transient for 5 minutes. The TTL is fixed and the cache is cleared automatically when a job is saved.

See also

Custom Fields (declarative filters)

Add custom fields to any plugin form - Job Form, Company Form, Candidate Profile, Application Form - with one add_filter call. The filter takes a single field-group schema; the plugin handles rendering, validation, persistence, REST exposure, and admin display.

The four filters

Filter Form
wcb_job_form_fields Post a Job (multi-step + single-page forms)
wcb_company_form_fields Company profile editor
wcb_candidate_form_fields Candidate profile editor
wcb_application_form_fields_groups Apply to a job

All four use the same field-group schema - once you've learned one, you've learned all four.

Schema

A field group looks like this:

[
    'group_id'    => 'employer_screening',
    'group_label' => __( 'Screening Questions', 'wp-career-board' ),
    'fields'      => [
        [
            'key'         => 'years_experience',
            'label'       => __( 'Years of relevant experience', 'wp-career-board' ),
            'type'        => 'number',
            'required'    => true,
            'min'         => 0,
            'max'         => 60,
        ],
        [
            'key'         => 'visa_status',
            'label'       => __( 'Current visa status', 'wp-career-board' ),
            'type'        => 'select',
            'required'    => true,
            'options'     => [
                'us-citizen'    => 'US Citizen',
                'green-card'    => 'Green Card',
                'h1b'           => 'H-1B',
                'opt'           => 'OPT',
                'needs-sponsor' => 'Needs sponsorship',
            ],
        ],
        [
            'key'         => 'portfolio_url',
            'label'       => __( 'Portfolio URL', 'wp-career-board' ),
            'type'        => 'url',
            'required'    => false,
            'placeholder' => 'https://',
        ],
    ],
]

Field types

Type Renders Stored as
text Single-line input string
textarea Multi-line textarea string
email Email input + validation string
url URL input + validation string
number Numeric input with min/max int / float
select Dropdown string (option key)
radio Radio button group string (option key)
checkbox Single boolean checkbox '1' / ''
multi-checkbox Multiple checkboxes array of option keys
date Date picker YYYY-MM-DD string

Example: Add a "Portfolio URL" field to the candidate profile

add_filter( 'wcb_candidate_form_fields', function( $groups ) {
    $groups[] = [
        'group_id'    => 'links',
        'group_label' => __( 'Online presence', 'wp-career-board' ),
        'fields'      => [
            [
                'key'      => 'portfolio_url',
                'label'    => __( 'Portfolio URL', 'wp-career-board' ),
                'type'     => 'url',
                'required' => false,
            ],
            [
                'key'      => 'github_url',
                'label'    => __( 'GitHub profile URL', 'wp-career-board' ),
                'type'     => 'url',
                'required' => false,
            ],
        ],
    ];
    return $groups;
} );

After this filter is in place:

  • The candidate profile editor renders both fields.
  • The fields validate on save (URL format).
  • Values persist as user meta _wcb_candidate_field_portfolio_url and _wcb_candidate_field_github_url.
  • They appear in the candidate's REST response on GET /wcb/v1/candidates/{id}.

Example: Add a screening question to the application form

add_filter( 'wcb_application_form_fields_groups', function( $groups, $job_id ) {
    $groups[] = [
        'group_id'    => 'screening',
        'group_label' => __( 'Quick screen', 'wp-career-board' ),
        'fields'      => [
            [
                'key'      => 'years_relevant',
                'label'    => __( 'Years of relevant experience', 'wp-career-board' ),
                'type'     => 'number',
                'required' => true,
            ],
            [
                'key'      => 'salary_expectation',
                'label'    => __( 'Salary expectation (USD/yr)', 'wp-career-board' ),
                'type'     => 'number',
                'required' => false,
            ],
        ],
    ];
    return $groups;
}, 10, 2 );

This adds the screening group to every job's apply form. To scope to specific jobs, branch on $job_id inside the callback.

Per-job custom fields (Pro field builder)

The above filter applies globally. For per-job configuration without writing PHP, install Pro and use the Field Builder admin page - the builder writes the same data structure to the wcb_field_groups / wcb_field_definitions Pro tables and contributes to the same filters automatically.

Where the data appears

Custom field values appear:

  • In the admin Edit Application screen - under a "Custom fields" section per group.
  • In the bulk CSV export - one column per field key.
  • In the REST API - under the custom_fields key of the job / company / candidate / application response.
  • In templates - via the Icon::svg() style helpers and direct postmeta reads (get_post_meta($id, '_wcb_application_field_<key>', true)).

Persistence keys

Per surface:

Filter Stored where Meta key prefix
wcb_job_form_fields wp_postmeta (job) _wcb_job_field_<key>
wcb_company_form_fields wp_postmeta (company) _wcb_company_field_<key>
wcb_candidate_form_fields wp_usermeta (candidate) _wcb_candidate_field_<key>
wcb_application_form_fields_groups wp_postmeta (application) _wcb_application_field_<key>

A bundle of all field values also lives at the corresponding _wcb_*_fields_bundle key for one-shot reads.

Application Editor (re-built)

The Edit Application admin screen has been rebuilt around the applicant - replacing the previously empty native post-edit screen with a full review surface that has everything an employer needs in one place.

What's on the screen

Section What it shows
Applicant card Avatar, name, email, phone (if collected), location
Cover letter Full text, formatted
Resume preview Inline preview with Open + Download buttons
Status changer Submitted / Reviewing / Shortlisted / Rejected / Hired - instant save on change
Quick action buttons Shortlist / Mark Hired / Reject / Message
Status history Full audit trail - who changed status, when, from / to
Custom fields Whatever the site has registered via wcb_application_form_fields_groups

Where to find it

wp-admin → Career Board → Applications → click any application row

Or via direct URL: /wp-admin/post.php?post=<id>&action=edit (the plugin redirects native post-edit URLs to the new admin screen).

Quick actions

The four quick-action buttons (Shortlist / Mark Hired / Reject / Message) each fire the corresponding workflow:

  • Shortlist - sets status to shortlisted, sends the configured shortlist email to the applicant, posts a status-change history entry.
  • Mark Hired - sets status to hired, sends hire email, posts to BuddyPress activity stream (Pro), and triggers the candidate- side "congratulations" notification.
  • Reject - sets status to rejected, sends rejection email (templated, customizable), records history.
  • Message - opens an inline reply composer that uses the same wp_mail() chokepoint as automated emails. Uses the configured email-template merge tags ({{candidate_name}}, {{job_title}}, etc.).

Status history

Every status change writes a row to the application's status history:

  • Who made the change (user ID + display name)
  • When (timestamp)
  • From → To (status slugs)
  • Optional note (employer can add a note when changing status)

The history shows in reverse-chronological order on the application screen. It's also exposed as application.status_history on the REST endpoint for ATS integrations.

Modular widget system

Every component on the application screen - applicant card, cover letter, resume preview, status changer, quick actions, status timeline - also works as a standalone shortcode you can embed anywhere. Widget IDs are namespaced with an application/ prefix:

[wcb_widget id="application/applicant-card" application_id="987"]
[wcb_widget id="application/cover-letter" application_id="987"]
[wcb_widget id="application/resume-preview" application_id="987"]
[wcb_widget id="application/status-timeline" application_id="987"]
[wcb_widget id="application/status-changer" application_id="987"]
[wcb_widget id="application/quick-actions" application_id="987"]

This is useful for:

  • Partner profile pages - embed the applicant card on a partner's candidate-facing page
  • Custom admin dashboards - composite widgets into a different arrangement using a dashboard plugin
  • Email templates - generate a snapshot of the applicant card to attach to a forwarded email

The interactive widgets respect the same capability as the admin screen - embedding [wcb_widget id="application/status-changer" application_id="987"] or application/quick-actions on a public page only renders for users granted the wcb/view-applications ability (backed by the wcb_view_applications capability). Users without it see nothing.

Bulk operations

The list table (one level up from the editor) supports bulk operations:

  • Bulk export to CSV - see Bulk CSV Export.
  • Bulk status change - set multiple applications to the same status in one action.
  • Bulk delete - same as native WP bulk delete on CPTs.

Permissions

Capability What it grants
wcb_view_applications Read the editor screen, run quick actions, change status (via the wcb/view-applications ability)
edit_post (per-application) Standard WP per-post edit gate; required to modify applicant data
wcb_employer role Site default - carries wcb_view_applications for applications belonging to their own jobs
manage_options Site admin override - can edit any application

See also

Capabilities & Roles

WP Career Board ships with 3 custom roles and 13 custom capabilities. Site administrators have every Career Board cap by default; the custom roles get a focused subset. Use this page to decide what to grant team members.

The custom roles

Role Slug Purpose
Employer wcb_employer Posts jobs, manages a company profile, and reviews applications
Candidate wcb_candidate Anyone who applies to jobs and manages a resume
Job Moderator wcb_board_moderator Reviews pending jobs and approves/rejects

Note on the Job Moderator slug: the role slug stays wcb_board_moderator for back-compatibility with existing assignments, but the display label is Job Moderator (renamed in 1.4.x because the role moderates jobs - boards are admin-only config and carry nothing to moderate).

Banning is not a role. There is no wcb_employer_banned role. Suspending an employer is a per-user flag (_wcb_employer_banned user-meta) set from the admin Employers screen. See Banning an employer below.

The 13 capabilities

Capability What it lets the user do
wcb_post_jobs Post a job, edit / republish own jobs
wcb_apply_jobs Apply to jobs, submit a resume on the apply form
wcb_manage_company Edit the company profile they're attached to
wcb_view_applications See incoming applications for their job posts
wcb_manage_resume Create / edit / publish a resume (Candidate flow)
wcb_bookmark_jobs Save jobs to "My Saved Jobs"
wcb_withdraw_application Withdraw an application after submitting
wcb_moderate_jobs Approve or reject pending jobs
wcb_access_admin_jobs Reach the admin Jobs queue (granted to moderators + admins)
wcb_view_analytics See the analytics dashboard (Pro)
wcb_manage_settings Configure Career Board settings, emails, integrations
wcb_access_employer_dashboard See the Employer Dashboard page
wcb_access_candidate_dashboard See the Candidate Dashboard page

Default capability map

Role Capabilities granted
Administrator All 13
Employer (wcb_employer) read, wcb_post_jobs, wcb_manage_company, wcb_view_applications, wcb_access_employer_dashboard
Candidate (wcb_candidate) read, wcb_apply_jobs, wcb_manage_resume, wcb_bookmark_jobs, wcb_access_candidate_dashboard, wcb_withdraw_application
Job Moderator (wcb_board_moderator) read, wcb_moderate_jobs, wcb_access_admin_jobs
Editor / Author None by default - grant wcb_post_jobs (and related caps) only if you want editorial staff to act as employers

The roles and admin caps are kept in sync on every load, so cap and label changes shipped in a plugin update reach existing installs without re-activation.

Granting capabilities to other roles

The easiest path is via a role manager plugin (User Role Editor, Members, etc.):

  1. Install your preferred role manager.
  2. Edit the target role.
  3. Tick the Career Board capabilities you want to grant.
  4. Save.

For "Editor as Employer" - a common editorial scenario:

Grant the Editor role:

  • wcb_post_jobs
  • wcb_view_applications
  • wcb_access_employer_dashboard
  • wcb_manage_company (so they can edit their company profile)

That gives editorial staff the ability to post and review jobs without the broader site-admin access.

Built-in registration

The plugin's registration flow creates accounts with these roles:

  • Employer registration - the Employer Registration block (placed on the "Employer Registration" page by the Setup Wizard) creates a user with the Employer (wcb_employer) role, which already carries wcb_post_jobs, wcb_manage_company, wcb_view_applications, and wcb_access_employer_dashboard.
  • Candidate registration - the Candidate Dashboard register tab creates a user with the Candidate (wcb_candidate) role.

By default any logged-in member can apply to jobs and manage a resume even without the Candidate role - jobs and resumes are commonly a side-feature of a community site. Turn on Settings → Job Listings → Require Candidate Role (or filter wcb_candidate_requires_role) to reserve the candidate experience for users who hold the candidate cap.

Banning an employer

Banning is done from the admin Employers list, not by changing the user's role:

  1. Go to WP Career Board → Employers.
  2. Use the Ban row action on a single employer, or tick several rows and choose Ban from the bulk-action menu.

This sets the _wcb_employer_banned user-meta flag, which the Abilities layer reads to strip every WCB ability from that user regardless of which caps their role carries.

Effects:

  • They lose every WCB ability - cannot post jobs, apply, manage a resume, or reach the dashboards.
  • Existing published jobs stay live. If you want them down, change the job's status to pending or draft separately.
  • They can still log in (they keep read).

To unban, use the Unban row or bulk action on the same screen, which deletes the meta flag.

How the plugin actually checks permissions

Internally Career Board uses the WordPress Abilities API (wp_register_ability + wp_is_ability_granted) rather than raw current_user_can calls. Each capability above maps to a namespaced ability slug:

Ability slug Backing capability
wcb/post-jobs wcb_post_jobs
wcb/apply-jobs wcb_apply_jobs
wcb/manage-settings wcb_manage_settings
wcb/moderate-jobs wcb_moderate_jobs
wcb/manage-resume wcb_manage_resume
wcb/bookmark-jobs wcb_bookmark_jobs
wcb/withdraw-application wcb_withdraw_application
wcb/manage-company wcb_manage_company
wcb/view-applications wcb_view_applications
wcb/access-employer-dashboard wcb_access_employer_dashboard
wcb/access-candidate-dashboard wcb_access_candidate_dashboard
wcb/view-analytics manage_options (admin-only; reserved for Pro analytics)

You only need to grant the underlying capability - the Abilities layer reads it. The wcb/manage-settings and wcb/view-analytics abilities are admin-gated and check manage_options directly rather than a dedicated cap. Both the cap form and wp_is_ability_granted() work in your own theme/plugin code, though wp_is_ability_granted() is the canonical call.

Note: a banned employer (the _wcb_employer_banned flag) is denied every WCB ability regardless of the caps their role holds.

Adding your own role

If you want a custom role (e.g. "Premium Employer") with a different mix:

add_action( 'init', function () {
    add_role( 'wcb_premium_employer', __( 'Premium Employer', 'my-addon' ), array(
        'read'                          => true,
        'wcb_post_jobs'                 => true,
        'wcb_view_applications'         => true,
        'wcb_manage_company'            => true,
        'wcb_access_employer_dashboard' => true,
        'wcb_view_analytics'            => true,  // Pro-only, no-op without Pro
    ));
});

To remove the role on uninstall, call remove_role() in the same file (or in your plugin's uninstall hook).

Troubleshooting permissions

"You don't have permission to do this" when an employer tries to post a job.

Check the employer's user role has wcb_post_jobs. The fastest check:

wp user get <login> --field=roles
wp user list-caps <login> | grep wcb_

"You don't have permission" when admin tries to change settings.

The settings screen is gated on manage_options (the wcb/manage-settings ability), which Administrator has by default. An Editor temporarily acting as admin does not have it.

Candidate registered but can't apply.

Their role might have been overridden by another plugin's registration flow. Check wp user get <login> --field=roles - it should be wcb_candidate. If it's subscriber or customer, either change the role manually or add wcb_apply_jobs to whatever role they got.

Company Profile Sidebar

The Company Profile block renders a right-column sidebar on every company single page (/companies/<slug>/). The sidebar always shows three useful Career Board cards out of the box, so the column is never wasted. Customisation is done with PHP filters, not the WordPress widget screen (see Customising the sidebar).

What it looks like

On desktop (>1024px) the company profile renders in a two-column grid:

  • Main column (left): the About, Company Details, and Open Positions sections.
  • Sidebar column (right, 320px): the three Career Board cards below.

On mobile (1024px and under) the sidebar stacks below the main content.

Default behaviour (no setup required)

The sidebar always renders these three Career Board blocks:

Block What it shows
Similar Companies (wp-career-board/similar-companies-card) Companies in the same industry as the company being viewed.
Recent Jobs (wp-career-board/recent-jobs) The 5 most recently published jobs across the board.
Job Alerts CTA (wp-career-board/job-alert-card) A small card linking candidates to the alerts signup flow.

You don't have to do anything to get these.

Note: earlier builds let admins place widgets in a "Company Profile Sidebar" widget area under Appearance → Widgets. That widget area was retired because generic footer/sidebar widgets were routinely misassigned there and rendered incorrectly on the company page. The sidebar is now driven entirely by the block and the filters below.

Customising the sidebar

Replace, reorder, or extend the three default cards with the wcb_company_sidebar_blocks filter. Each entry is a Gutenberg block-comment string passed to do_blocks():

add_filter(
    'wcb_company_sidebar_blocks',
    function ( array $blocks, int $company_id ): array {
        // Append the Job Stats card to the defaults.
        $blocks[] = '<!-- wp:wp-career-board/job-stats /-->';
        return $blocks;
    },
    10,
    2
);

Return an empty array to render no cards. To inject arbitrary markup before or after the cards, use the companion action hooks - both run inside the <aside class="wcb-cp-sidebar"> element:

add_action( 'wcb_company_sidebar_before', function ( int $company_id ) { /* echo markup */ } );
add_action( 'wcb_company_sidebar_after',  function ( int $company_id ) { /* echo markup */ } );

Which Career Board blocks fit well in the sidebar

These Career Board blocks are 320px-friendly and work well as sidebar cards:

  • Similar Companies (wp-career-board/similar-companies-card) - same-industry companies, with optional Company ID for use on non-company pages.
  • Recent Jobs (wp-career-board/recent-jobs) - latest published jobs.
  • Featured Jobs (wp-career-board/featured-jobs) - featured listings grid.
  • Job Alerts CTA (wp-career-board/job-alert-card) - signup nudge card.
  • Job Stats (wp-career-board/job-stats) - aggregate counts.

All ship as shortcodes too if you're using a page builder:

  • [wcb_similar_companies count="5"]
  • [wcb_recent_jobs count="5"]
  • [wcb_featured_jobs perPage="3"]
  • [wcb_job_alert_card]
  • [wcb_job_stats]

Suppression of the theme's own sidebar

On company singles, Career Board hides the active theme's primary sidebar (#secondary, .widget-area, aside.sidebar, etc.) and forces the parent content column to full width. This is intentional: themes often pre-populate their sidebars with Archives, Categories, Recent Posts widgets that don't make sense on a company page. The company-profile block takes over that space and renders its own sidebar instead.

If you want the theme's primary sidebar to remain visible on company pages too, you can filter it back in with a tiny mu-plugin:

add_action(
    'wp_enqueue_scripts',
    function () {
        if ( is_singular( 'wcb_company' ) ) {
            wp_add_inline_style(
                'wp-career-board-company-profile-style',
                '.wcb-company-page #secondary { display: block !important; }'
            );
        }
    },
    20
);

This is rarely needed - the in-block sidebar is the cleaner UX - but it's available as an override.

Standalone use on other pages

These sidebar blocks also work outside the company-profile context:

  • wp-career-board/similar-companies-card has a Company ID attribute in the editor inspector. Drop the block on any page and set the ID to anchor it to a specific company. Leave blank when used inside the Company Profile Sidebar (it auto-resolves there).

  • wp-career-board/job-alert-card has fully editable title, body, button text, and URL. Use it on landing pages, footer columns, or wherever you want a "Get Job Alerts" CTA.

Theme compatibility

Tested across:

  • BuddyX Pro (the company-page CSS overrides BuddyX's grid-template-columns: 978px 260px to single-column on company singles so our content fills the freed space).
  • Reign.
  • Astra, Kadence, GeneratePress (collapse via .ast-container, .container-grid selector overrides).
  • Twenty Twenty-Three / Four / Five (block themes work out of the box).

If you find a theme where the layout looks wrong, file an issue with the active theme name plus a screenshot - the per-theme CSS shim is a one-line addition.

Where to go next

Content Filtering

New in 1.7.0 - job listings are now filtered server-side based on member blocking, so a blocked member's content never reaches the people who blocked them (or the people they blocked).

What it does

When a member blocks another member (see Moderation), Career Board hides that member's job listings from the other side of the block, everywhere a job can be seen:

  • The Find Jobs / job listings archive and blocks.
  • The single job page, both the pretty-permalink URL and the REST response - a blocked employer's job 404s instead of loading.
  • The mobile REST API, using the same filtering logic as the website.

The filtering is mutual: it doesn't matter which side did the blocking. If either member blocked the other, neither one sees the other's job listings.

Where it runs

This is a server-side filter, not something hidden with CSS in the browser. The job listings query and the single-job lookup both exclude blocked authors before the results are ever sent to the browser or the REST client, so there's no way to see a blocked member's listings by disabling JavaScript, calling the REST API directly, or using the mobile app.

Configuration

There is no settings screen for this - it is automatic and always on wherever member blocking exists. It runs entirely off each member's own block list, so there's nothing for the site owner to turn on, tune, or configure. If a site owner wants to remove the effect of a block (for example, to review a listing during a dispute), that's done by unblocking from the member's account, or by an admin editing user meta directly - there is no admin override toggle.

  • Moderation - reporting and blocking members, and suspending candidate accounts.
  • Reported Jobs - the separate flow for reporting a specific job listing (as opposed to a member).

AI Features

AI-assisted job description writing, candidate screening, and applicant matching.

AI Features Overview

WP Career Board can use AI across the hiring flow: job description writing, natural-language job search, candidate-to-job matching, applicant ranking with summaries, and cover-letter drafting. All AI features ship in the Pro plugin. The Free plugin defines the gate filters (wcb_ai_description_enabled, wcb_ai_ranking_available, wcb_ai_matching_available) and the UI surfaces, so Pro wires the AI in without changes elsewhere.

This page summarises what's in the current release (1.4.3), what's gated behind an AI provider being configured, and how the pieces fit together. If you're on Free, treat this as a feature preview: the flows here are what you get when you upgrade.

What ships today (1.4.3)

The AI feature set matured in Pro 1.3.0 and has shipped in every release since. All of the following are live in code:

Feature Surface Who uses it
Job embeddings Background: every new job is embedded on wcb_job_created into the wcb_ai_vectors table. System
Index existing jobs (backfill) "Index existing jobs" button under Settings -> AI Settings embeds jobs that existed before AI was enabled. Site owners
AI Chat Search block wcb/ai-chat-search block (a chat-style search box). An AI Job Search page carrying this block is auto-created when Pro sets up. Closest-matched jobs come back via POST /wcb/v1/ai/match. Candidates
AI candidate matches ("Recommended for you") Top-N jobs matched to a candidate's resume, available via GET /wcb/v1/candidates/{id}/matches and surfaced for the current candidate. Candidates
AI Job Description Writer "Generate with AI" button on the post-a-job form, gated behind wcb_ai_description_enabled. Sends title + company type + location to the provider; returns structured HTML. Employers
AI applicant ranking One-click "Rank by AI fit" on the Employer Dashboard. Each applicant gets a 0-100 fit score, a one-line reason, and a TL;DR summary, sorted best-first via GET /wcb/v1/ai/ranked-applications/{job_id}. Employers
Applicant TL;DR summaries A one-to-two-sentence neutral summary of each applicant's background, shown alongside the fit score in the dashboard list and detail. Employers
Auto-score on submit Optional. When enabled, new applications are scored in the background (cron) so the dashboard shows AI fit instantly. Employers
AI cover-letter writer In the job apply panel, candidates generate a tailored cover letter from their resume and the job, edit it, then submit via POST /wcb/v1/jobs/{job_id}/ai-cover-letter. Candidates

In Free, every path is gated. The Chat Search block renders nothing for visitors (and a configure hint for admins), the description and cover-letter buttons are hidden, the ranking controls don't appear, and the AI REST routes aren't registered. No broken UI surfaces in Free.

The two-provider model

AI is configured per task, not as a single global provider:

  • Analysis & ranking (completions) drives the description writer, applicant ranking, TL;DR summaries, the cover-letter writer, and the chat search assistant. Choose Anthropic Claude, OpenAI, or Ollama.
  • Embedding & matching drives job embeddings, AI Chat Search, and candidate matches. Choose OpenAI or Ollama (Claude has no embeddings API, so it is not an embedding option).

Each provider has its own API key (or base URL for Ollama) and its own model selection. You can run, for example, Claude for ranking copy and OpenAI for embeddings at the same time. See 02-setup-and-providers.md.

What gets cached and re-billed

Applicant fit scores, reasons, and summaries are cached in application post meta (_wcbp_ai_fit_score, _wcbp_ai_fit_reason, _wcbp_ai_summary, _wcbp_ai_scored_at). Re-opening the dashboard never re-bills the model; ranking computes only what is missing. Force a re-score by passing $force to AiModule::score_application() from a custom integration.

Embeddings are stored once per job in wcb_ai_vectors and reused for every search. Query embeddings (chat search, candidate match) are computed per request and not stored.

Free vs Pro at a glance

Free Pro
Job posting form Full editor Full editor + AI description writer button
Candidate dashboard / resume Resume Builder, manual profile fill Same + resume feeds AI matching, ranking, and cover letters
Search bar Keyword search, taxonomy filters Keyword + filters + AI Chat Search block + AI Job Search page
Apply panel Cover-letter field (manual) Same + "Generate with AI" cover-letter button
Applications screen / dashboard List, status filter, manual review Same + AI fit score, reason, TL;DR, "Rank by AI fit", optional auto-score
AI Settings tab Hidden Visible under WP Admin -> Career Board -> Settings -> AI Settings
Database Standard tables only Adds wcb_ai_vectors for embeddings

When AI is worth turning on

Turn it on if:

  • Your board has more than ~30 active jobs and candidates struggle to find the right one with keyword search alone.
  • You want the description-writer assist to speed up job posting.
  • You triage many applicants per role and want a fit-score plus TL;DR to prioritise reviews.
  • You want candidates to draft cover letters from their resume in one tap.

Skip it if:

  • You're under 20 active jobs and a handful of applications a week. The description writer might still help, but matching and ranking won't move the needle yet.
  • You can't share job / candidate text with a third-party LLM provider for privacy / compliance reasons. (Use Ollama locally; see 02-setup-and-providers.md.)

How it works under the hood

When AI is enabled and the relevant provider is configured:

  1. On job publish: Pro hooks wcb_job_created and calls AiModule::generate_job_embedding(). The job title + content are embedded by the configured embedding provider and stored as a binary-packed float vector in wcb_ai_vectors.
  2. On AI Chat Search: the candidate's query is embedded the same way, then cosine-similarity-compared against every stored job vector. Top 10 matches are returned via POST /wcb/v1/ai/match.
  3. On candidate matching: the candidate's resume text (built by the Pro Resume module via the wcbp_candidate_resume_data filter) is embedded and matched against job vectors via GET /wcb/v1/candidates/{id}/matches.
  4. On description writer: the form sends title + company type + location to POST /wcb/v1/jobs/ai-description. The completion provider returns a structured-HTML description; the editor inserts it.
  5. On applicant ranking: each application's job title + candidate resume text is sent to the completion provider with a JSON scoring prompt. Returns {score, reason, summary} per application, cached in post meta. GET /wcb/v1/ai/ranked-applications/{job_id} returns the list sorted best-first.
  6. On auto-score (optional): when wcbp_ai_auto_rank is on, Pro hooks wcb_application_submitted and schedules a background wcbp_ai_score_application cron event so the score is ready before the employer looks.
  7. On cover-letter generation: the candidate's resume text + the job are sent to the completion provider via POST /wcb/v1/jobs/{job_id}/ai-cover-letter; the returned draft is inserted into the cover-letter field for editing.

Embedding paths go through the configured embedding driver; completion paths through the configured completion driver. Both drivers are OpenAI / Anthropic Claude / Ollama (or one registered via wcbp_ai_provider_drivers).

What gets sent to the AI provider

The privacy-relevant breakdown:

Feature What's sent
Job embedding (on publish / backfill) The job title and description as plain text.
AI Chat Search The candidate's typed query string.
AI candidate matches The candidate's flattened resume text.
AI Description Writer The job title, company type, and location.
Applicant ranking / TL;DR The job title and the applicant's flattened resume text.
AI cover letter The job title, a job-content excerpt, and the candidate's resume text.

For privacy-sensitive deployments, run Ollama locally - see 02-setup-and-providers.md. Nothing leaves your server.

What it doesn't do

  • No auto-rejection. Ranking returns scores; nothing acts on them automatically. Every decision still lands with the employer.
  • No auto-matching emails. Job Alerts use keyword / filter match, not AI semantic match.
  • No content generation outside the writer and cover-letter tools. AI does not auto-fill candidate bios, company "about us" sections, or similar.
  • No data sold or shared. All API calls are between your site and the configured provider directly - Wbcom never sees or proxies the data.

Where to go next

Setup & Providers

Pro feature. The AI Settings tab only appears when WP Career Board Pro is installed and active. On Free this page applies once you upgrade. (Pro features work regardless of license status - the license drives automatic updates only.)

WP Career Board Pro chooses AI providers per task: one provider for analysis & ranking (completions) and a separate provider for embedding & matching. Each has its own API key and model. You can switch at any time.

The two roles

Role Powers Allowed providers
Analysis & ranking (completions) Description writer, applicant ranking, TL;DR summaries, cover-letter writer, chat assistant Anthropic Claude, OpenAI, Ollama
Embedding & matching Job embeddings, AI Chat Search, candidate matches OpenAI, Ollama

Claude has no embeddings API, so it can only be the analysis provider. If you want Claude for ranking copy, pair it with OpenAI or Ollama for embeddings.

Provider comparison

Provider Embeddings model (default) Completions model (default) Where it runs Cost ballpark
OpenAI text-embedding-3-small gpt-4o-mini OpenAI servers (USA) $0.02 per 1M embedding tokens, $0.15 / 1M input + $0.60 / 1M output for completions
Anthropic Claude Not supported claude-sonnet-4-6 Anthropic servers (USA) Sonnet-tier per-token pricing for completions. Requires OpenAI or Ollama for embeddings.
Ollama nomic-embed-text llama3 Your server / your hardware Free (your compute)

Each provider's model is selectable on the AI Settings tab - Claude (Haiku / Sonnet / Opus), OpenAI (completion model + embedding model), Ollama (model names). Defaults are listed above.

Recommended default: OpenAI for both roles. Best balance of quality, cost, and zero setup. Use Claude as the analysis provider when you want better description and cover-letter copy. Use Ollama when content must not leave your server.

Cost estimation (OpenAI)

Rough back-of-envelope for a typical mid-size board:

Activity Tokens per event Events per month Monthly cost
Job publish (embedding) ~300 in 100 new jobs ~$0.001
AI Chat Search query ~50 in 5,000 searches ~$0.0005
Applicant ranking + TL;DR ~2500 in / ~180 out 800 scored (cached after first) ~$1.40
Job Description Writer ~500 in / ~500 out 100 generations ~$0.31
Cover-letter writer ~1500 in / ~250 out 300 generations ~$0.50
Total per month ~$2.20

Scores are cached per application, so re-opening the dashboard does not re-bill. For a large board (10x the above), expect $15-$25 / month. Set a monthly cap on your OpenAI billing dashboard - that's the surest way to catch a runaway loop. Ollama is free but uses your CPU / GPU.

Step 1 - choose providers

  1. Go to WP Admin -> Career Board -> Settings -> AI Settings.
  2. Analysis & ranking provider - choose Anthropic Claude, OpenAI, Ollama, or None.
  3. Embedding & matching provider - choose OpenAI, Ollama, or None.

If you can't see the AI Settings tab, check that Pro is active.

Step 2 - enter keys (or base URL) and models

Each field on the tab links out to where to get the key, and the Ollama field notes that it is free and self-hosted.

OpenAI

  1. Sign in at platform.openai.com.
  2. Billing -> Payment methods - add a card. OpenAI requires a payment method even for low-volume use.
  3. API keys -> Create new secret key. Copy the sk-... value immediately (you can't view it again).
  4. Paste into the OpenAI API Key field on the AI Settings tab.
  5. Optionally set the OpenAI completion model and embedding model (defaults gpt-4o-mini and text-embedding-3-small).
  6. Set a Monthly budget on the OpenAI dashboard. Recommendation: $20 / month for a starting board, and raise if you actually hit it.

Anthropic Claude

  1. Sign in at console.anthropic.com.
  2. Add a payment method.
  3. API keys -> Create key. Copy the sk-ant-... value.
  4. Paste into the Anthropic API Key field.
  5. Optionally pick the Claude model (Haiku / Sonnet / Opus; default claude-sonnet-4-6).
  6. Remember: Claude can only be the analysis provider. Set the embedding provider to OpenAI or Ollama as well, or AI Chat Search and candidate matching stay off.

Ollama (self-hosted)

  1. Install on your server: curl -fsSL https://ollama.com/install.sh | sh
  2. Pull the required models:
    ollama pull nomic-embed-text
    ollama pull llama3
    
    On a 4 GB VPS this takes a few minutes and uses about 5 GB of disk for both models.
  3. Confirm Ollama is reachable: curl http://localhost:11434/api/tags should return a JSON list including both models.
  4. In AI Settings, set the Ollama Base URL to http://localhost:11434 (or wherever Ollama is bound). No API key is needed.
  5. Optionally set the Ollama completion/embedding model names (defaults llama3 and nomic-embed-text).
  6. Server sizing: completions on llama3 require ~6 GB RAM and run slowly on CPU-only servers. For decent latency, run on a host with a GPU or use a smaller quantised variant (llama3:8b-instruct-q4_K_M).

Step 3 - save

Click Save AI Settings. Configuration is stored in these options:

Option Holds
wcbp_ai_completion_provider Analysis & ranking provider slug
wcbp_ai_embedding_provider Embedding & matching provider slug
wcbp_ai_openai_key OpenAI API key
wcbp_ai_anthropic_key Anthropic API key
wcbp_ai_ollama_url Ollama base URL
wcbp_ai_openai_model / wcbp_ai_openai_embedding_model OpenAI models
wcbp_ai_anthropic_model Claude model
wcbp_ai_ollama_model / wcbp_ai_ollama_embedding_model Ollama models
wcbp_ai_auto_rank Auto-score applicants on submit (on/off)

The legacy single-provider options wcbp_ai_provider, wcbp_ai_api_key, and wcbp_ai_base_url were removed in 1.3.0. AI reads only the per-task options above.

Key security

API keys are never written back into the settings page HTML. Each key field renders empty with a "saved" indicator and only updates when you type a new value. A stored key is not exposed in the page source - so an empty key field after saving is expected, not a bug.

Verifying your setup

There is no separate "test connection" button. Configuration is validated the first time a real AI call happens. To verify:

  • Analysis provider: open the post-a-job form and click Generate with AI - a successful generation confirms the completion provider + key.
  • Embedding provider: run Index existing jobs (below) and then search on the AI Job Search page - results confirm the embedding provider + key.

Backfilling embeddings for existing jobs

Embeddings are generated automatically at wcb_job_created time. Jobs that existed before AI was enabled have no embeddings and won't appear in AI Chat Search or candidate matches until you backfill.

The AI Settings tab has an "Index existing jobs" button that calls AiModule::backfill_job_embeddings() and reports how many jobs were embedded. Each call is bounded (up to a few hundred jobs) so the request stays responsive; run it again to continue paging through a large catalog.

The button is disabled with a clear note when no embedding provider (OpenAI or Ollama) is set, and explains why if you try - Claude cannot index for matching.

For very large catalogs you can also loop in WP-CLI:

wp eval '
$ai = new \WCB\Pro\Modules\Ai\AiModule();
$n  = $ai->backfill_job_embeddings( 500 );
echo "Embedded $n jobs\n";
'

Run it off-hours - each call is a provider API request.

Privacy and data flow per provider

Provider Where data goes Logged by provider Used for training?
OpenAI OpenAI's US servers via TLS Yes (kept up to 30 days for abuse monitoring) No, API data is opted out of training by default
Anthropic Claude Anthropic's US servers via TLS Yes (kept up to 30 days) No, API data is not used for training
Ollama Stays on your server. Never leaves. Only if you log it yourself N/A

If you're under GDPR / CCPA / HIPAA constraints, use Ollama for both roles.

Switching providers

You can change providers at any time without losing data:

  • Existing job vectors are kept per provider. If you switch the embedding provider from OpenAI (1536-dim) to Ollama (768-dim) the dimensions don't match and cosine similarity returns 0 for every comparison - so AI Chat Search returns no results until you re-run Index existing jobs against the new provider.
  • Existing options are simply overwritten on save. A blank key field keeps the previously stored key (see "Key security" above).

Disabling AI

Set both provider dropdowns to None and save. Effects:

  • AiModule::is_enabled() returns false.
  • AI Chat Search block renders nothing for visitors (admins see a configure hint).
  • The description writer, cover-letter, and ranking controls disappear.
  • /ai/match, /candidates/{id}/matches, /ai/ranked-applications/{job_id} return empty lists; /jobs/ai-description and /jobs/{id}/ai-cover-letter return a 503 with wcb_ai_disabled.
  • No new embeddings are generated.
  • Stored wcb_ai_vectors rows and cached scores are kept (no destructive change). If you re-enable AI later, everything resumes against the existing data.

To fully clean up: deactivate Pro, and on uninstall the AI table goes with it.

Common setup errors

The top three:

  • "Invalid API key" - wrong key or wrong provider selected. Re-copy from the provider dashboard. OpenAI keys start sk-, Anthropic keys start sk-ant-. Strip whitespace.
  • "Connection refused" (Ollama) - Ollama isn't running or the Base URL is wrong. ps aux | grep ollama to confirm; restart with systemctl restart ollama if needed.
  • "AI is not configured" (503) - the completion provider is None, or set but missing its key. Open AI Settings and finish the analysis & ranking provider.

See 06-troubleshooting.md for the full list.

Where to go next

AI Features for Candidates

Pro feature surface. These flows activate when WP Career Board Pro is active and the relevant AI provider is configured. On Free the keyword search and standard apply flow still work.

This page covers what candidates experience with AI on (1.4.3): the AI Chat Search, AI candidate matches ("Recommended for you"), and the AI cover-letter writer in the apply panel.

A chat-style natural-language search box that returns semantically relevant jobs - not just keyword matches.

Where it lives

The AI Chat Search block (wcb/ai-chat-search) is placed on a page via the block editor. When Pro sets up, an AI Job Search page carrying this block is created automatically. The site owner can also add the block to the Find Jobs page, above the standard keyword search. If your board doesn't have it, ask the admin to add the block.

What candidates type

Anything natural-language. Examples that work well:

  • "Remote React job, US time zones, $100k+"
  • "Junior data analyst position, willing to relocate to Berlin"
  • "Marketing role at a B2B SaaS startup, 10-50 people, hybrid OK"
  • "Senior backend engineer, Rust or Go, no on-call"

What doesn't work as well:

  • One-word queries ("developer"). For a single word, the standard keyword search is faster and more predictable.
  • Queries that depend on context outside the listings ("the job from last week's newsletter"). The AI doesn't know about your other pages.

What candidates see

The block presents a conversation-style box:

  • The typed query appears as a message bubble.
  • A spinner for 1-3 seconds while the query is embedded and matched.
  • An assistant reply noting how many jobs matched, followed by a list of matched job cards (title, company), ranked by relevance, not date.

The results render in-place via the Interactivity API - no page reload happens when they refine the query. If a search fails, the box shows a "Search failed. Please try again." message rather than breaking.

What it can't do

  • It won't enforce filters you didn't type. "Any job" returns the top jobs by general relevance. The standard keyword filters still work as a fallback.
  • It doesn't store search history per candidate. Each query is embedded, matched, and forgotten on the backend.
  • It doesn't auto-recommend jobs by email. Job Alerts use keyword / filter match, not AI semantic match.
  • It needs job embeddings to exist. Embeddings are generated at wcb_job_created. Jobs from before AI was enabled appear only after the admin runs Index existing jobs (see 02-setup-and-providers.md).
  • It has a per-user rate limit: 30 AI calls per hour across all AI features. Heavy testers will hit a 429 and need to wait.

Tips for candidates

  • Be specific about non-negotiables. "Remote" surfaces; "no on-call" surfaces; "must use modern frameworks" is too vague.
  • Salary specifics help. "$80-100k" filters better than "good salary."
  • Include location AND remote preference. "Remote, US time zones, preferably East Coast" is a complete instruction.
  • If results feel off, refine - add one more constraint and resubmit.

Beyond typing a query, AI can match jobs to a candidate's resume automatically. The candidate's resume (built in the Pro Resume Builder) is flattened into text, embedded, and compared against every job vector. The top jobs are returned as "Recommended for you" cards.

This runs through GET /wcb/v1/candidates/{id}/matches for a specific candidate, and POST /wcb/v1/ai/match for the currently signed-in candidate. It needs an embedding provider (OpenAI or Ollama) configured and job embeddings to exist.

Quality depends on how complete the candidate's resume is - the more sections filled in (experience, skills, summary), the sharper the matches.

AI cover-letter writer

In the job apply panel, a candidate can generate a tailored cover letter instead of writing one from scratch.

The flow

  1. Open a job and start to apply.
  2. Click Generate with AI next to the cover-letter field.
  3. Pro sends the candidate's resume text plus this job (title and a content excerpt) to the analysis provider via POST /wcb/v1/jobs/{job_id}/ai-cover-letter.
  4. A first-person draft (about 150-200 words, using only resume-supported details) is inserted into the cover-letter field.
  5. The candidate edits the draft, then submits the application as normal.

Notes

  • The button appears only when Pro is active and the analysis provider is configured (the apply panel reads an aiCoverEnabled flag).
  • The draft uses only details the resume supports - it won't invent experience. A sparse resume produces a thin letter.
  • Same 30-calls-per-hour rate limit applies.
  • If the candidate applies with a Resume Builder resume that has no PDF, Pro generates and attaches the PDF automatically, so the application still carries a downloadable file.

How resume data reaches the AI

Pro's Resume module implements the wcbp_candidate_resume_data filter: it returns the candidate's grouped resume sections, which the AI module flattens into text for matching, ranking, and cover letters. This is wired in Pro core - no add-on is required. Resumes imported from WP Job Manager Resumes are read too (legacy experience / education meta), so matching and cover letters work on migrated data.

There is no separate "auto-parse an uploaded PDF into profile fields" step - candidates fill in the Resume Builder (or import), and that structured data is what feeds the AI.

What candidates get without Pro

Capability Free Pro 1.4.3
Browse all jobs Yes Yes
Keyword search + filters Yes Yes
Apply to jobs Yes Yes
Resume upload (attaches to applications) Yes Yes
Save jobs to bookmarks Yes Yes
Get email notifications Yes Yes
Natural-language AI search (AI Chat Search block) No Yes
"Recommended for you" AI candidate matches No Yes
AI cover-letter writer in the apply panel No Yes
Semantic match in job alerts No No

Where to go next

AI Features for Employers

Pro feature surface. Employers on Free still get the full job-posting form, the full applications screen, and standard candidate review. The AI-assisted shortcuts below appear when the site has Pro active and the relevant provider configured.

This page covers what employers can do with AI in 1.4.3: the Job Description Writer during posting, and AI applicant ranking with fit scores, reasons, and TL;DR summaries on the Employer Dashboard.

AI Job Description Writer

A button on the post-a-job form that turns a few form fields into a job description draft. Employers always review and edit the output before publishing - nothing is auto-posted.

Where it lives

On the Post a Job form (Employer Dashboard or /post-a-job/), above the description editor:

  • A "Generate with AI" button (icon + label). Present on both the full job form and the simple job form.
  • Visible only when:
    • Pro is active.
    • The wcb_ai_description_enabled filter resolves to true (Pro's AiModule::is_enabled() returns true when an analysis or embedding provider is configured).
    • The employer's role has wcb_post_jobs.

What gets sent to the AI

The writer endpoint (POST /wcb/v1/jobs/ai-description) accepts three fields:

Field Source on the form
title Job title input
company_type Company type / industry input
location Job location input

These are composed into a prompt asking the model to write a compelling job description (role overview, responsibilities, requirements) and to return clean semantic HTML (<h3>, <p>, <ul><li>), no markdown or code fences.

The flow

  1. Fill in the basics: job title, company, location, type.
  2. Click "Generate with AI." Spinner appears for 5-15 seconds (depends on provider).
  3. A structured-HTML draft appears in the editor.
  4. Edit it. Add company-specific details, tone, anything the AI missed. The output is a starting point.
  5. Submit the job as normal.

Tips for employers

  • A good title produces a better description. "Senior Backend Engineer (Rust + Tokio, billing service)" produces a more specific draft than "Software Engineer."
  • The output is generic by default. AI doesn't know your company. Plan to edit at least 30% of the draft for accuracy and tone.
  • Run it through your own eye before publishing. First-pass drafts often miss specific perks, your diversity statement, or HR legal language. Treat it like a junior intern's first draft.
  • Each generation costs API credits (~$0.003 on OpenAI's pricing per generation). Regenerating to get the tone right is still cheap.

Limits

  • Output is provider-determined - no per-request token cap in the plugin code.
  • Provider quality matters. Claude (Sonnet) writes more naturally; OpenAI is a bit more formal; Ollama / llama3 is the weakest writer.
  • Rate limit: 30 AI calls per user per hour, shared across all AI features.

AI applicant ranking

Pro scores each application against its job (0-100 fit + a one-line reason + a neutral TL;DR summary) and surfaces it right on the Employer Dashboard - no custom code required.

Where it lives

On the Employer Dashboard applications view, when an analysis provider is configured (the wcb_ai_ranking_available filter is true):

  • A "Rank by AI fit" control sorts the loaded applications best-first.
  • Each applicant row shows an AI fit score (e.g. "87%"), the reason, and a TL;DR summary of the candidate's background.
  • The detail view shows the same fit, reason, and summary.

Under the hood the dashboard calls GET /wcb/v1/ai/ranked-applications/{job_id}, which returns each application's {application_id, score, reason, summary} sorted by score.

Caching - you are not re-billed

Fit score, reason, and summary are cached per application in post meta (_wcbp_ai_fit_score, _wcbp_ai_fit_reason, _wcbp_ai_summary, _wcbp_ai_scored_at). Re-opening the dashboard reuses cached values; ranking only computes applications that have never been scored. A force re-score is available via AiModule::score_application( $id, true ) from a custom integration.

Auto-score on submit (optional)

Under Settings -> AI Settings, enable "Auto-score applicants on submit" (wcbp_ai_auto_rank). When on, Pro hooks wcb_application_submitted and schedules a background wcbp_ai_score_application cron event ~30 seconds after each new application, so the dashboard shows AI fit instantly without anyone clicking "Rank by AI fit." It's skipped when no analysis provider is configured.

What the score means

  • 80-100 - strong match. Resume / profile genuinely aligns with the job. Worth interviewing.
  • 60-79 - partial match. Some required skills present, others missing. Read in full before deciding.
  • 40-59 - weak match. Limited overlap. Useful as triage signal, not as a filter.
  • Below 40 - minimal match. Most fields aren't aligned.

The score is one signal, not the answer. Culture fit, location, salary expectations, and soft skills are not captured.

How it's computed

Pro sends the job title and the candidate's resume text to the analysis provider with a JSON prompt asking for {score, reason, summary}. The candidate's resume text comes from the Pro Resume module via the wcbp_candidate_resume_data filter (wired in Pro core - no add-on required). The model reply is parsed even when it's wrapped in code fences, so scores are real rather than always zero.

Important caveats

  • Don't auto-reject by score. AI bias is real; a low score on a great candidate (e.g. a career-changer) shouldn't short-circuit human review. Pro never auto-rejects.
  • Sparse resumes score low. A candidate who hasn't filled in the Resume Builder gives the AI little to work with.
  • Re-score is on demand. Cached scores stay until you force a recompute or auto-score handles a brand-new application.

Privacy considerations

Ranking is the most data-heavy AI feature - each applicant's resume text is sent to the analysis provider on first scoring (then cached). If your hiring policy doesn't allow that, set the analysis provider to Ollama to keep everything on your server.

What employers get without Pro

Capability Free Pro 1.4.3
Post a job Yes Yes
Manual job description editor Yes Yes
AI Description Writer button No Yes
Review applicants Yes Yes
Sort by date, status Yes Yes
AI fit score + reason on the dashboard No Yes
AI TL;DR applicant summaries No Yes
One-click "Rank by AI fit" No Yes
Auto-score applicants on submit No Yes
Application pipeline (Kanban) No Yes
Bulk actions on applications Yes Yes

Where to go next

AI Block & Developer Surface

Pro-only surface. The block, REST endpoints, and Pro filters below are registered by wp-career-board-pro. The Free plugin defines the gate filters (wcb_ai_description_enabled, wcb_ai_ranking_available, wcb_ai_matching_available, wcb_ai_completion_available) and the UI surfaces so Pro - or an add-on shipping its own AI driver - can flip them on.

This page documents the AI surface that ships in 1.4.3.

AI Chat Search block

The candidate-facing natural-language search bar (chat-style).

Block reference

Property Value
Name wcb/ai-chat-search
Editor category Widgets
Render mode Server-side render (render.php) + Interactivity API frontend
Pro-only? Yes - registered by Pro only

Attributes

One attribute is exposed:

Attribute Type Default Description
placeholder string Describe your ideal job... Input placeholder text.

If you need more (button label, max results, relevance bar), copy blocks/ai-chat-search/render.php into a child plugin and customise.

How to add it to a page

  1. An AI Job Search page carrying this block is created automatically when Pro sets up. To add it elsewhere:
  2. Open the page in the block editor.
  3. Add a new block; search for AI Chat Search.
  4. Optionally edit the placeholder text in the block sidebar.
  5. Save / publish.

Render contract

Server-side, the block:

  1. Hard-gates on AiModule::is_enabled(). If AI is off, visitors get nothing; users with the wcb/manage-settings ability see a "AI search is not configured" hint pointing to AI Settings.
  2. Reads the placeholder attribute and outputs an Interactivity API root with a chat-message area, an input/submit form, and a results area.
  3. Loads view.js as a script module (no jQuery, no admin-ajax). It imports the shared @wcb/fetch helper (15s AbortController timeout).
  4. On submit, the JS POSTs { query } to /wcb/v1/ai/match with the wp_rest nonce. It reads data.jobs from the response and renders the matched job cards (title + company).

AI Description Writer (Free hook, Pro behaviour)

The post-a-job form (full and simple) has a "Generate with AI" button next to the description editor, gated behind wcb_ai_description_enabled:

// In Free's job form render
if ( apply_filters( 'wcb_ai_description_enabled', false ) ) : ?>
    <button ... data-wp-on--click="actions.generateDescription">
        Generate with AI
    </button>
<?php endif;

Pro's AiModule::is_enabled() returns true for this filter when an analysis or embedding provider is configured. An add-on can short-circuit Pro:

add_filter( 'wcb_ai_description_enabled', '__return_true' );

When clicked, the JS calls POST /wcb/v1/jobs/ai-description with title, company_type, and location. The response is { description: "<h3>...</h3>..." } (structured HTML) which the JS injects into the editor.

AI cover-letter writer (apply panel)

The job-single apply panel shows a "Generate with AI" cover-letter button when Pro is active and the completion provider is configured. On click the JS POSTs to /wcb/v1/jobs/{job_id}/ai-cover-letter and inserts the returned { cover_letter: "..." } text into the cover-letter field for the candidate to edit before submitting.

REST endpoints

Five AI endpoints exist. All live in api/endpoints/class-ai-endpoint.php and inherit from WCB\Pro\Api\ProRestController.

Method Route Permission Body / Query Response
POST /wcb/v1/ai/match logged-in user { query } (current user implied for matching) enriched match cards (see below)
GET /wcb/v1/candidates/{id}/matches own candidate row OR wcb/manage-ai path id enriched match cards
GET /wcb/v1/ai/ranked-applications/{job_id} wcb/view-applications path job_id [{application_id, score, reason, summary}]
POST /wcb/v1/jobs/ai-description wcb/post-jobs title, company_type, location { description }
POST /wcb/v1/jobs/{job_id}/ai-cover-letter logged-in user path job_id { cover_letter }

Match card shape

/ai/match and /candidates/{id}/matches return enriched cards (jobs that aren't published are skipped):

[
  {
    "job_id": 123,
    "score": 0.82,
    "score_pct": 82,
    "title": "Senior React Engineer",
    "company": "Acme",
    "url": "https://example.com/job/senior-react-engineer/",
    "location": "Remote"
  }
]

The list passes through the wcbp_ai_candidate_matches filter before it is returned, so add-ons can re-rank or decorate the cards.

Rate limiting

Every endpoint applies a transient-based 30 calls per user per hour ceiling (wcbp_ai_rate_{user_id}). Hitting the cap returns:

{
  "code": "wcb_rate_limit",
  "message": "AI request limit reached. Please try again later.",
  "data": { "status": 429 }
}

This is global per user across all five endpoints. The limit isn't exposed as a filter; override the permission logic in a child class to change it.

Common error codes

Code Meaning
wcb_ai_disabled (HTTP 503) Completion provider unset or its key missing. Returned from /jobs/ai-description and /jobs/{id}/ai-cover-letter; the match / ranked endpoints return an empty list instead.
wcb_job_not_found (HTTP 404) Cover-letter route given an id that isn't a wcb_job.
wcb_rate_limit (HTTP 429) Per-user hourly ceiling hit.
rest_forbidden (HTTP 403) Caller lacks the ability check.

Filters Pro fires

Filter Args Returns Use case
wcb_ai_description_enabled bool bool True when AI is enabled (any provider). Gates the description button.
wcb_ai_ranking_available bool bool True when the completion provider is configured. Gates the dashboard ranking controls.
wcb_ai_completion_available bool bool True when the completion provider is configured.
wcb_ai_matching_available bool bool True when the embedding provider is configured. Gates matching surfaces.
wcb_pro_ai_enabled bool bool True when Pro AI is active. Free fires it in api/endpoints/class-settings-endpoint.php to set the ai_matching flag in the /wcb/v1 app-config payload.
wcbp_ai_provider_drivers array $builtin, string $credential, string $credential array<slug, factory> Register a custom AI provider driver.
wcbp_ai_provider_requires_api_key bool $requires_key, string $provider bool Override whether the active provider needs an API key (self-hosted gateways).
wcbp_candidate_resume_data int $user_id grouped resume array Supply a candidate's resume data. Implemented by Pro's Resume module; override to feed your own data.
wcbp_ai_candidate_matches array $enriched, int $user_id array Post-process the enriched match list before it is returned.
wcbp_ai_ranked_applications array $ranked, int $job_id array Post-process the ranked-applications list before it is returned.
wcbp_ai_claude_model string $model string Override the Claude completion model.

Free hooks Pro consumes

Hook Where What Pro does
wcb_job_created Free fires after a job is created AiModule::generate_job_embedding() embeds title + content into wcb_ai_vectors.
wcb_application_submitted Free fires after an application is submitted AiModule::maybe_schedule_scoring() queues background scoring when wcbp_ai_auto_rank is on.

Cron action Pro fires

Action Args Fired by Listener
wcbp_ai_score_application int $app_id Single event scheduled on submit (auto-rank) AiModule::run_scheduled_scoring() scores the application in the background.

Abilities used by AI endpoints

Ability Used by
wcb/manage-ai /candidates/{id}/matches when the caller isn't the candidate
wcb/view-applications /ai/ranked-applications/{job_id}
wcb/post-jobs /jobs/ai-description
wcb/manage-settings the block's admin-only "not configured" hint

Grant the underlying capability (wcb_view_applications, wcb_post_jobs, etc.) - the Abilities API reads it. See ../admin-guide/14-capabilities-and-roles.md.

The AiModule public API

If you're writing a Pro add-on that needs AI directly:

use WCB\Pro\Modules\Ai\AiModule;

$ai = new AiModule();

// Configuration checks.
$ai->is_enabled();             // analysis OR embedding configured
$ai->is_completion_enabled();  // analysis provider configured
$ai->is_embedding_enabled();   // embedding provider configured

// Top-N job matches for a candidate.
$matches = $ai->match_candidate_to_jobs( $user_id, 10 );
// list<array{job_id: int, score: float}>

// Score one application (cached; pass true to force a recompute).
$score = $ai->score_application( $app_id );
// array{application_id, score: int, reason: string, summary: string}

// All applications for a job, ranked best-first (each cached).
$ranked = $ai->rank_applications( $job_id );

// Backfill embeddings for existing published jobs (bounded per call).
$count = $ai->backfill_job_embeddings( 500 );

// Flatten a candidate's resume to text (via wcbp_candidate_resume_data).
$text = $ai->candidate_resume_text( $user_id );

// Per-task drivers (for custom prompts).
$completion = $ai->get_completion_driver();
$embedding  = $ai->get_embedding_driver();
$reply  = $completion->complete( 'Your prompt here' ); // string|WP_Error
$vector = $embedding->embed( 'Text to embed' );        // float[]|WP_Error

Registering a custom AI provider

To ship a driver for Cohere, Mistral, a private LLM, etc., implement AiDriverInterface and register it via the filter:

<?php
namespace MyAddon\AI;

use WCB\Pro\Modules\Ai\AiDriverInterface;

class CohereDriver implements AiDriverInterface {

    public function __construct( private string $credential ) {}

    public function embed( string $text ): array|\WP_Error {
        // Call Cohere embed endpoint; return float[] or WP_Error.
    }

    public function complete( string $prompt ): string|\WP_Error {
        // Call Cohere chat endpoint; return string or WP_Error.
    }

    public function provider_name(): string {
        return 'cohere';
    }
}

add_filter(
    'wcbp_ai_provider_drivers',
    function ( array $drivers, string $credential ): array {
        $drivers['cohere'] = static fn(): AiDriverInterface
            => new \MyAddon\AI\CohereDriver( $credential );
        return $drivers;
    },
    10,
    2
);

The complete() method takes only a prompt string; the embed() method takes a text string and returns a float vector (or WP_Error).

Notes for add-on authors

  • No shortcode wrapper for the AI block - it is block-editor / page-builder only.
  • No wp wcb ai * WP-CLI namespace - drive AI from wp eval using the AiModule public methods above (for example to backfill embeddings in bulk).
  • Scores are cached in application post meta (_wcbp_ai_fit_score, _wcbp_ai_fit_reason, _wcbp_ai_summary, _wcbp_ai_scored_at). Read them directly if you only need the cached value.

Where to go next

AI Troubleshooting

What can go wrong with AI features in 1.4.3, in order of how often it actually happens.

If you're on Free and don't see the AI Settings tab at all - that's expected, not a bug. AI Settings only appears with Pro active.

"Invalid API key" / "Authentication failed"

The most common setup error.

Check:

  1. Right key for the right provider. OpenAI keys start sk-, Anthropic keys start sk-ant-, Ollama doesn't use a key. Copy from the provider dashboard, not from a stale email.
  2. No leading / trailing whitespace. Particularly when pasting from a terminal - a hidden newline breaks auth.
  3. Key isn't disabled or expired. Confirm on the provider dashboard.
  4. Right organisation / project (OpenAI). If your OpenAI account has multiple projects, the key must belong to the project that has the billing source attached.
  5. You actually entered a new key. Key fields render empty after saving (keys are never written back into the page for security). An empty field after save means the stored key is kept - it does not mean the key was lost. To replace it, type the new value.

If the key works in curl but not in the plugin, check that the host firewall isn't stripping outbound HTTPS to non-whitelisted domains.

"Quota exceeded" / "Rate limit hit"

Three different things can produce this kind of error:

Provider-side monthly cap

OpenAI: Dashboard -> Limits -> check current usage vs. cap. Raise the monthly cap or wait for the next billing cycle.

Anthropic: Console -> Limits -> adjust monthly cap.

Ollama: Doesn't have a quota - but it can run out of memory. Watch dmesg for OOM-killer events.

Provider-side per-minute rate limit

HTTP 429 from OpenAI / Anthropic means you're hitting their per-minute or per-day ceiling. Reduce concurrent calls (e.g. slow down a bulk backfill).

Plugin-side rate limit (Pro)

The AI endpoints enforce a 30 calls per user per hour ceiling via a transient. Response:

{
  "code": "wcb_rate_limit",
  "message": "AI request limit reached. Please try again later.",
  "data": { "status": 429 }
}

This is shared across all five AI REST endpoints per user. Heavy testing during setup will hit it. Wait an hour, or in dev clear the transient (replace {user_id} with the user's ID):

wp transient delete "wcbp_ai_rate_{user_id}"

"Connection refused" (Ollama)

Ollama isn't running, isn't reachable from the WP host, or the Base URL is wrong.

  1. Is the Ollama service up? systemctl status ollama (or ps aux | grep ollama).
  2. Is it bound to the right address? Default is localhost:11434. Test from the WP host: curl http://localhost:11434/api/tags.
  3. Are the required models installed? ollama list should show both nomic-embed-text and llama3. If not: ollama pull nomic-embed-text && ollama pull llama3.
  4. If Ollama is on a different server, the Base URL needs to point there AND Ollama needs to bind to that interface (OLLAMA_HOST=0.0.0.0:11434 systemctl restart ollama).

AI Chat Search returns no results

Several possibilities:

No embeddings exist yet

Embeddings are generated at wcb_job_created. Jobs that existed before AI was turned on have no vectors and won't appear.

Fix: click "Index existing jobs" on the AI Settings tab to backfill. See 02-setup-and-providers.md.

Embedding provider not configured

AI Chat Search needs an embedding provider (OpenAI or Ollama), not just the analysis provider. If you only set Claude, matching is off - Claude has no embeddings API. Set the embedding provider too.

Embedding provider was switched

If you changed the embedding provider (e.g. OpenAI -> Ollama), the dimension count changes (1536 -> 768). Cosine similarity returns 0 for every mismatched pair, so search returns nothing. Re-run "Index existing jobs" against the new provider.

The query is too short / too vague

Very short queries ("dev") return whatever's broadly closest - usually not useful. Tell candidates to type at least a phrase.

Provider call failed

AiModule::match_candidate_to_jobs() returns an empty array on any provider error, and the block shows "Search failed. Please try again." Check wp-content/debug.log for entries around the failed search.

AI Description Writer button is missing

  1. Pro inactive. Check that Pro is active.
  2. No provider configured. AI Settings -> at least one provider must be set with a valid key (or Base URL for Ollama).
  3. Employer doesn't have wcb_post_jobs. Check via wp user list-caps {login} | grep wcb_.
  4. wcb_ai_description_enabled filter is returning false. An add-on may be overriding it.

Description Writer returns gibberish / wrong language

  1. Provider quality. Ollama / llama3 is the weakest writer. Switch the analysis provider to OpenAI or Claude for production.
  2. Inputs are sparse. The writer uses only title, company_type, and location. Vague inputs produce vague output.
  3. Wrong language. The AI generates in the same language as the inputs. Write title / company / location in the target language.

"AI is not configured" (HTTP 503)

Returned by POST /wcb/v1/jobs/ai-description and POST /wcb/v1/jobs/{id}/ai-cover-letter when:

  • The analysis & ranking provider (wcbp_ai_completion_provider) is unset or none, OR
  • It's set but the matching credential is empty (wcbp_ai_openai_key / wcbp_ai_anthropic_key for OpenAI / Claude, wcbp_ai_ollama_url for Ollama).

Open AI Settings, finish the analysis & ranking provider, save.

Applicant ranking returns zero scores across the board

  1. Sparse or missing resume. Scores come from the candidate's resume text. A candidate who hasn't filled in the Resume Builder gives the AI little to score. The resume-data hook (wcbp_candidate_resume_data) is wired in Pro core, so the connection itself works - the issue is usually empty resumes.
  2. Analysis provider not configured. Ranking needs the completion provider set with a valid key.
  3. A model returning malformed JSON. The scorer extracts the first {...} object and tolerates code fences, but a provider that returns no JSON at all yields a zero. Check debug.log and consider switching the analysis provider.

"Rank by AI fit" does nothing / control missing

  1. Analysis provider not configured. The dashboard ranking control is gated on wcb_ai_ranking_available (completion provider configured).
  2. No applications loaded for the job. Ranking sorts the loaded list; if there are no applications there's nothing to rank.
  3. Scores are cached. Re-ranking won't re-bill or change cached scores. To force a recompute, call AiModule::score_application( $id, true ).

Auto-score doesn't run

  1. Toggle off. Enable "Auto-score applicants on submit" in AI Settings (wcbp_ai_auto_rank).
  2. Analysis provider not configured. Auto-score is skipped when the completion provider isn't set.
  3. WP-Cron not firing. Auto-score runs on a scheduled single event (wcbp_ai_score_application) ~30s after submission. On a low-traffic site WP-Cron may lag - confirm cron is running (wp cron event list).

Application ranking endpoint returns 403

The caller doesn't have wcb_view_applications. Grant via:

wp user add-cap {login} wcb_view_applications

or use a role manager plugin.

Cover-letter button missing or returns 503

  1. Pro inactive or analysis provider not configured - the apply panel reads an aiCoverEnabled flag that depends on the completion provider being set.
  2. 404 instead of a letter - the route was given an id that isn't a published wcb_job.
  3. Thin letter - the writer only uses resume-supported details. Fill in the Resume Builder for a richer draft.

"Provider returned empty response"

Rare. Either:

  1. The provider hit an internal error and returned an empty body. Retry - usually transient.
  2. The plugin's HTTP request hit a connect timeout (the shared fetch helper aborts after 15s on the block side).
  3. (Ollama) The model is still loading on first request after a server restart. Try once more - subsequent requests are fast.

AI spend is suddenly higher than expected

  1. A backfill running. "Index existing jobs" (or the WP-CLI backfill) embeds every selected job - that's the cost.
  2. Forced re-scoring. Normal dashboard use reuses cached scores; a custom integration calling score_application( $id, true ) re-bills.
  3. A custom plugin re-saving jobs. Each wcb_job_created fires an embedding call. Grep your custom code for hooks on wcb_job_created.
  4. Provider dashboard -> Activity shows request counts per day. If a spike doesn't match a known event, set the monthly cap and investigate.

Disable AI quickly in an emergency

Three paths:

  1. AI Settings -> set both providers to None. Save.
  2. WP-CLI:
    wp option update wcbp_ai_completion_provider none
    wp option update wcbp_ai_embedding_provider none
    
  3. Database:
    UPDATE wp_options SET option_value = 'none'
    WHERE option_name IN ( 'wcbp_ai_completion_provider', 'wcbp_ai_embedding_provider' );
    

All AI calls stop immediately. UI elements that depend on AI hide cleanly. Stored embeddings and cached scores are kept.

Things that look broken but aren't

  • Empty API-key fields after saving. Keys are never written back into the page for security. The stored key is intact.
  • No "Test connection" button. Verify via a real generation or a search after indexing.
  • No wp wcb ai * WP-CLI commands. Use wp eval with the AiModule public methods.
  • Re-ranking shows the same scores. Scores are cached per application on purpose, so re-opening the dashboard never re-bills.
  • "Index existing jobs" disabled. It greys out with a note when no embedding provider is set - Claude alone cannot index for matching.

How to file an AI bug report

If something genuinely doesn't work and these steps didn't help, file on the support board with:

  1. The providers you're using (analysis + embedding).
  2. What you did to trigger the issue (exact buttons / queries).
  3. What you expected vs. what you saw.
  4. Anything from wp-content/debug.log matching wcb_ai or wcbp_ai.
  5. The provider dashboard activity timestamp around the failure.

Don't include actual candidate resumes or full applicant data - shape, not contents.

Where to go next

Pro Features

Pro-only capabilities included with the Pro plugin.

Job Map

Pro feature - Requires the WP Career Board Pro plugin to be installed and active. Every Pro feature works as soon as the plugin is active; the license key only powers automatic updates, it never gates functionality.

The Job Map block displays an interactive map of job locations alongside your listings. As candidates filter jobs, the map updates in real time - no page reload.

How It Works

The Job Map shares the same search state as the Job Listings and Job Filters blocks. When a visitor searches by keyword, filters by category, or selects a job type, the map instantly updates to show only matching pins.

Clicking a pin on the map opens a small popup with the job title and a "View Job" link.

Requirements

  • Jobs must have a Location set (the wcb_location taxonomy term, e.g. city, region, or country)
  • Locations are geocoded to latitude/longitude automatically when the job is created

A job's coordinates are stored in the _wcb_lat and _wcb_lng post meta. You can also set these directly when importing jobs from CSV (the lat and lng columns).

Map Providers

The Job Map supports three providers. The default is Leaflet with OpenStreetMap tiles, which works out of the box with no API key.

Provider API key needed Notes
Leaflet / OpenStreetMap No Default. Zero configuration. Uses OpenStreetMap tiles and Nominatim geocoding.
Google Maps Yes (API key) Set the key under Map Settings. Get one at console.cloud.google.com.
Mapbox Yes (access token) Set the token under Map Settings. Get one at account.mapbox.com.

Choosing a Provider

  1. Go to Career Board -> Settings -> Integrations
  2. Find the Map Settings card
  3. Pick a Map Provider from the dropdown
  4. If you chose Google Maps or Mapbox, paste the API key / access token in the matching field
  5. Click Save Integrations

The provider can also be overridden per board. Open a board (Career Board -> Settings -> Boards -> Edit) and set the Map Provider field in the Board Settings meta box. A board's setting takes priority over the global default; if a board leaves it on the default, the global Map Provider is used.

Adding the Job Map

  1. Open your jobs page in the WordPress editor
  2. Click + and search for "Job Map" (block name wcb/job-map)
  3. Insert the block

Recommended layout - two columns with Map on the left, Listings on the right:

[ Job Search ] [ Job Filters ]
[ Job Map     ] [ Job Listings ]

This gives candidates both a spatial view and a list view simultaneously.

Block Settings

Setting Default Description
Map Height 480 Height of the map canvas in pixels

Multi-Board Engine

Pro feature - Requires the WP Career Board Pro plugin to be installed and active. Every Pro feature works as soon as the plugin is active; the license key only powers automatic updates, it never gates functionality.

The Multi-Board Engine lets you segment one WordPress install into multiple independent job boards (for example "Tech Jobs", "Marketing Jobs", "Remote Only"). Each board carries its own per-board configuration and scopes the jobs assigned to it.

Boards are administrator-only configuration. They are created and managed from wp-admin; they are not a per-employer or front-end self-service feature.

What You Get

  • Multiple boards - create as many boards as you need
  • Board scoping - a job is linked to a board via its _wcb_board_id meta, so listings can be filtered to a single board
  • Per-board settings - each board has its own credit cost, moderation mode, expiry, currency, map provider, and AI toggle
  • Board-scoped listings - the Job Listings block accepts a boardId attribute (or [wcb_job_listings boardId="42"] shortcode) to render only one board's jobs anywhere on the site

Where Boards Live

Boards are managed at Career Board -> Settings -> Boards. The free plugin creates one board automatically on activation, named Main Board, which becomes the default.

Creating a Board

  1. Go to Career Board -> Settings -> Boards
  2. Click Add Board (this opens the standard WordPress editor for the board)
  3. Enter the board Title - this is the board name
  4. Configure the Board Settings meta box (see below)
  5. Click Publish

The Boards list shows each board's job count, number of pipeline stages, and credit cost, with Edit and Delete actions. Deleting a board removes its pipeline stages and unlinks (but does not delete) any jobs assigned to it - those jobs stay visible but are no longer board-restricted.

Board Settings

Open a board and use the Board Settings meta box on the board edit screen:

Setting Description
Credit Cost Per Job Credits deducted when an employer posts to this board. 0 means free.
Moderation "Use global default", "Auto-publish", or "Requires approval" for jobs posted to this board.
Job Expiry (days) Days until jobs on this board expire. 0 follows the site-wide default.
Currency Salary currency for this board (from the plugin currency catalog).
Map Provider Leaflet / OpenStreetMap, Google Maps, or Mapbox for this board's Job Map.
Enable AI Features Turns the AI features on for jobs and applicants on this board.

Assigning Jobs to a Board

A job's board is stored in its _wcb_board_id meta. Jobs can be assigned a board through the posting flow, through the CSV importer (the board_id column), or by an integration that sets the meta. A job posted without a board falls back to the default board (wcb_default_board_id).

Default Board

The first board created on activation ("Main Board") is stored in the wcb_default_board_id option and is used for any job that is posted without an explicit board. There is no separate "set as default" control in the Boards list - the default is the board recorded in that option.

Per-Board Pipeline Stages

Each board can carry its own application pipeline stages, stored in the wcb_application_stages table keyed by board_id. The Boards list shows how many stages each board has. The stages drive the status columns shown on the employer dashboard's Applications board (the List / Board Kanban toggle).

Rendering a Single Board's Jobs

To show one board's jobs on a page, set the Board attribute on the Job Listings block, or use the shortcode form:

[wcb_job_listings boardId="42" perPage="6"]

Replace 42 with the board's post ID. Without a boardId, the Job Listings block shows jobs across all boards.

Analytics Dashboard (Pro)

The Analytics module gives you a snapshot of your job board's activity -- jobs, applications, users, views, and credit flow -- from a single dashboard screen.

Pro feature - Requires the WP Career Board Pro plugin to be installed and active. Every Pro feature works as soon as the plugin is active; the license key only powers automatic updates, it never gates functionality.

What Is Tracked

Metric Description
Total Jobs Count of published wcb_job posts
Total Applications Count of published wcb_application posts
Total Employers Number of users with the wcb_employer role
Total Candidates Number of users with the wcb_candidate role
Job Views (30 days) Page view events logged in the wcb_job_views table during the last 30 days
Top 5 Jobs The five most-viewed jobs, with individual view counts
Application Rate Average number of applications per published job
Credits Issued Lifetime sum of all topup entries in the credit ledger
Credits Spent Lifetime sum (absolute value) of all deduction entries in the credit ledger

Job view tracking is provided by WP Career Board (free). All other metrics are computed directly from WordPress post counts, user roles, and the credit ledger table.

Where to Find Analytics

Go to Career Board -> Analytics in your WordPress admin.

CSV Export

You can export the full credit ledger as a CSV file for accounting or auditing purposes. The export is served by a REST endpoint (GET /wp-json/wcb/v1/analytics/credits.csv) gated on the credit-management ability.

  1. Go to Career Board -> Analytics
  2. Click the credit ledger export control
  3. A file named wcb-credits-YYYY-MM-DD.csv downloads immediately

CSV Columns

Column Description
ID Ledger row ID
Employer WordPress user ID associated with the entry
Amount Credit amount (positive for top-ups, negative for deductions)
Type Entry type: topup, hold, deduction, or refund
Job Associated item ID, normally the job post ID (0 if not applicable)
Note Human-readable note attached to the entry
Date Timestamp the entry was created

Rows are exported newest-first (ordered by creation date, descending).

Notes

  • The credit ledger is append-only -- no entries are ever edited or deleted, so the export is a reliable audit trail
  • Job view data requires the free plugin's wcb_job_views table; if the table is absent, view metrics return 0
  • The stats are cached in a short-lived (5 minute) transient. The cache is cleared immediately whenever credits are topped up or consumed, so credit totals stay current

Job Feed / XML Syndication (Pro)

The Job Feed publishes all your live jobs as an XML feed at a fixed URL. Submit this URL to Indeed, Glassdoor, LinkedIn, and other job aggregators to automatically syndicate your listings.

Pro feature - Requires the WP Career Board Pro plugin to be installed and active. Every Pro feature works as soon as the plugin is active; the license key only powers automatic updates, it never gates functionality.

Feed URL

https://yoursite.com/wcb-jobs.xml

The feed is disabled by default. Enable it in Career Board -> Settings -> Job Feed.

Feed Format

The feed uses the Indeed XML format, which is also accepted by Glassdoor, LinkedIn, and most other major job aggregators. The document opens with a <source> element carrying <publisher> (your site name) and <publisherurl> (your site URL), followed by one <job> entry per listing.

Each <job> entry contains:

Field Source
<title> Job post title
<date> Publication date (RFC-822 GMT)
<referencenumber> WordPress post ID
<url> Public permalink
<company> _wcb_company_name meta
<city> First term from the wcb_location taxonomy
<country> Currently emitted empty
<description> Job description (HTML stripped, wrapped in CDATA)
<salary> Formatted min-max range, e.g. $80,000 - $120,000 / yearly
<jobtype> First term from the wcb_job_type taxonomy
<email> Contact email from feed settings
<expirationdate> _wcb_deadline meta

The salary uses the job's own currency symbol from the plugin currency catalog (USD, EUR, GBP, CAD, AUD, INR, SGD), so a EUR or INR job is not exported with a hardcoded dollar sign.

Setup

Step 1: Enable the Feed

  1. Go to Career Board -> Settings -> Job Feed
  2. Toggle Enable Feed on
  3. The feed URL appears immediately below the toggle

Step 2: Set the Contact Email

Enter the email address to include in the <email> field of every job entry. This is the address aggregators and candidates use to contact you about listings. It defaults to the WordPress admin email.

Step 3: Submit to Indeed

  1. Log in to the Indeed Employer Portal
  2. Go to Integrations -> Job Feed
  3. Enter your feed URL: https://yoursite.com/wcb-jobs.xml
  4. Indeed re-fetches the feed every 24 hours

Pagination

The feed returns up to 200 jobs per page. If you have more than 200 published jobs, append a start parameter to retrieve additional pages:

https://yoursite.com/wcb-jobs.xml?start=0    <- jobs 1-200
https://yoursite.com/wcb-jobs.xml?start=200  <- jobs 201-400
https://yoursite.com/wcb-jobs.xml?start=400  <- jobs 401-600

Caching

Each feed page is cached for one hour using WordPress transients. The cache key includes a version number stored in the wcbp_feed_version option, and that version is bumped every time a job is saved. The next request after a save therefore reads a fresh feed (its key no longer matches the old cached copy), and stale per-page caches expire naturally within the hour. The feed also sends a Cache-Control: public, max-age=3600 header for CDN edge caching.

Disabling the Feed

Toggle Enable Feed off. The URL returns a 404 response instead of XML. Aggregators that poll the URL will stop receiving new listings.

Progressive Web App (Pro)

The PWA module turns your job board into an installable Progressive Web App. Candidates can add it to their phone's home screen and browse job listings even with a poor connection.

Pro feature - Requires the WP Career Board Pro plugin to be installed and active. Every Pro feature works as soon as the plugin is active; the license key only powers automatic updates, it never gates functionality.

What the PWA Provides

Feature Description
Install prompt Browsers prompt candidates to install the job board as a home screen app
Offline browsing Previously visited job listing pages load from cache when the device is offline
Network-first forms Application forms and dashboards always try the network first - never served stale from cache
Branded splash screen The app name ({Site Name} Jobs), your chosen theme color, and the WordPress Site Icon are used for the install and splash experience
VAPID key pair A VAPID public/private key pair is generated once on plugin activation and stored in options, ready for future push-notification support

How It Works

The module serves two files from your site's root:

  • /wcb-manifest.json -- Web App Manifest describing the app name, icon, theme color, and display mode
  • /wcb-service-worker.js -- Service worker that intercepts fetch events on WCB pages

The service worker uses stale-while-revalidate for in-scope job pages (paths starting with /jobs/, /companies/, /candidates/): the cached version loads instantly while a fresh copy is fetched in the background. Apply requests and dashboard pages use network-first: they always try the network and fall back to cache only if the network is unavailable.

The manifest <link> tag and the service-worker registration script are only injected on WCB-related pages (the job archive, single job pages, and the configured Jobs archive / Employer Dashboard / Candidate Dashboard pages).

App Icon

The manifest pulls its icon from the WordPress Site Icon (Settings -> General -> Site Icon). The plugin does not ship a default icon: if no Site Icon is set, the manifest is served without an icon entry and the browser falls back to the favicon. Set a Site Icon to get a branded install/splash icon.

Setup

Configure the Theme Color

  1. Go to Career Board -> Settings -> Integrations
  2. Find the PWA Settings card
  3. Pick a Theme Color -- this is the brand color shown in the mobile browser chrome bar and on the splash screen when the app launches
  4. Click Save Integrations

The default theme color is #4f46e5 (indigo).

The manifest and service worker are served directly from /wcb-manifest.json and /wcb-service-worker.js (the module matches the request URI on init - it does not rely on permalink rewrite rules), so no permalink flush is required for the PWA.

Browser Support

The PWA install prompt and service worker work in:

  • Chrome and Edge (Android and desktop)
  • Safari 16.4+ (iOS and macOS)
  • Firefox (service worker only -- no install prompt on Firefox for Android)

Browsers that do not support service workers continue to work normally -- the module degrades gracefully.

Verifying Installation

Open your job listings page in Chrome on Android. After a few seconds, Chrome displays an Add to Home screen banner at the bottom of the browser. Tap it to install. The app opens in standalone mode (no browser toolbar) with your chosen theme color.

On desktop Chrome, look for the install icon in the address bar.

CSV Import (Pro)

The CSV importer lets you bulk-import jobs from a CSV file. Imported jobs default to Pending status for editorial review, though you can set a different status per row.

Pro feature - Requires the WP Career Board Pro plugin to be installed and active. Every Pro feature works as soon as the plugin is active; the license key only powers automatic updates, it never gates functionality.

CSV Import

Finding the Import Screen

Go to Career Board -> Import and look for the CSV → Jobs card (marked Pro). The card is added to the free plugin's Import page by Pro.

Download the Sample File

Click Download Sample CSV to get a correctly structured template with two example rows. Use it as a starting point for your data.

CSV Column Reference

Required

Column Description
title Job title -- the only required column

Content

Column Description
description Full job description (HTML allowed)
status pending (default), publish, or draft. Any other value falls back to pending.
deadline Application deadline -- any parseable date format, stored as YYYY-MM-DD

Salary

Column Accepted Values
salary_min Integer (e.g. 80000)
salary_max Integer (e.g. 120000)
salary_currency USD, EUR, GBP, CAD, AUD, INR, SGD
salary_type yearly, monthly, or hourly

If salary_min is greater than salary_max, the importer swaps them automatically and records a warning.

Flags

Column Accepted Values
remote yes, no, 1, or 0
featured yes, no, 1, or 0

Company

Column Description
company Company name text
company_id WordPress post ID of an existing company post

Application

Column Description
apply_url External application URL
apply_email Application contact email

Taxonomies

Separate multiple values with commas or pipes. Terms are created automatically if they do not exist.

Column Taxonomy
categories Job category
job_types Job type (e.g. `Full-time
locations Location
experience Experience level
tags Job tags

Geo and Board

Column Description
lat Latitude (decimal)
lng Longitude (decimal)
board_id WordPress post ID of the target job board (Multi-Board)

Custom Fields

Add any field key from the Field Builder as a column header. The importer matches each non-standard column against the custom field keys defined in the Field Builder (the wcb_field_definitions table); recognized keys are stored on the imported job. Columns that do not match a known field key are ignored.

Running the Import

  1. Select your CSV file using the file picker
  2. Click Import
  3. A results summary shows how many jobs were imported, skipped, and whether any warnings occurred
  4. Go to Career Board -> Jobs and review the Pending listings before publishing

Error Handling

Condition Result
File not found or unreadable Fatal error -- no rows processed
Missing title column Fatal error -- no rows processed
Row has wrong column count Row skipped, error logged in summary
Empty title on a row Row skipped, error logged in summary
Invalid currency or salary type Field skipped for that row
Invalid date Field skipped for that row

Migrating from WP Job Manager

The recommended path for moving listings from WP Job Manager into WP Career Board is the CSV import described above: export your WPJM listings to CSV, map the columns to the WCB column names in this reference, and import.

Note: a code-level WP Job Manager importer class exists in the plugin but is not currently exposed through any admin screen, REST route, or WP-CLI command, so it is not a self-service feature in this release. Use the CSV import for WPJM data.

Integrations

BuddyPress, Reign Theme, BuddyX Pro, and other plugin integrations.

BuddyPress Integration

When BuddyPress is active on your site, WP Career Board automatically connects with it to add your job board into the community experience.

What You Get

  • Two BuddyPress member types, Employer and Candidate, registered for your community
  • A BuddyPress activity item posted to the site-wide stream every time an employer publishes a job
  • Member types kept in sync automatically when a user is given the WP Career Board employer or candidate role

Requirements

  • BuddyPress active and configured
  • WP Career Board 1.4.3

The BuddyPress integration first shipped in WP Career Board 1.0.0 and has been part of every release since.

Setup

No configuration required. Activate both plugins and WP Career Board detects BuddyPress automatically (it checks for the buddypress() function) and boots the integration.

Activity Stream Integration

When an employer publishes a job, WP Career Board adds a BuddyPress activity item to the site-wide activity stream. The item is posted under the job author, links to the published job, and reads like "{name} posted a new job: {job title}". Members can comment, react, or share the listing through the normal BuddyPress activity tools.

Technical detail for developers:

  • The activity item is registered under the wp-career-board activity component with the activity type wcb_job_posted.
  • It is created on the wcb_job_created action, only when the job's status is publish.
  • The activity item_id is the job post ID.

Note: only job publishing generates an activity item. Submitting an application does not post to the activity stream.

Member Types

WP Career Board registers two BuddyPress member types on bp_init:

  • Employer - applied to users with the WP Career Board employer role (wcb_employer)
  • Candidate - applied to users with the WP Career Board candidate role (wcb_candidate)

Member types are assigned automatically through the set_user_role hook: when a user is set to the wcb_employer role they receive the employer member type, and the wcb_candidate role maps to the candidate member type. Because the assignment runs on role changes, the member type is applied the next time a user's role is set (for example through the Setup Wizard sample data, an employer or candidate signup, or an admin role edit).

Once member types are assigned you can use BuddyPress member-type tools and queries (for example member-type directory URLs or bp_get_member_type() in your templates) to surface Employers and Candidates separately.

BuddyBoss Platform

WP Career Board does not ship BuddyBoss-specific code. Because BuddyBoss Platform provides the same buddypress() bootstrap and the same member-type and activity functions, the BuddyPress integration above loads and runs on BuddyBoss Platform as well. The member types and the job-posted activity item work the same way. There are no BuddyBoss-only features.

Disabling Activity Items

WP Career Board does not expose a dedicated on/off setting or filter for the job-posted activity item. If you want BuddyPress active but do not want the job activity in the stream, use BuddyPress's own activity tools to hide the wcb_job_posted activity type, for example by removing it from the registered activity actions or by filtering it out of the stream query in your own code. Site administrators can also delete individual activity items from the activity stream.

BuddyX and BuddyX Pro Integration

WP Career Board includes built-in support for the BuddyX and BuddyX Pro themes by Wbcom Designs. The same integration covers both themes, because their content width and layout tokens are identical. When either theme is active, the job board adopts the theme's accent color and uses BuddyX-tuned page templates for job listings without any extra configuration.

What You Get

  • A BuddyX-compatible single job template for wcb_job posts
  • A BuddyX-compatible archive template for the jobs post-type archive
  • An accent-color bridge: WP Career Board re-maps its --wcb-primary color to your BuddyX accent color, so buttons, links, and highlights match the theme palette
  • A compatibility stylesheet (buddyx-compat.css) loaded on every WP Career Board page so the plugin's blocks sit cleanly inside BuddyX layouts
  • An #OpenToWork badge on candidate member profiles (see below)

Requirements

  • BuddyX or BuddyX Pro theme active
  • WP Career Board 1.4.3

The integration is selected by the active theme's template slug: it loads when the slug is buddyx or buddyx-pro.

Setup

No configuration required. Activate BuddyX or BuddyX Pro along with WP Career Board and the integration boots automatically on after_setup_theme.

Accent Color Bridge

WP Career Board reads the BuddyX accent color from the Customizer and injects it as the plugin's primary color, so WP Career Board components inherit your theme palette in light and dark mode. BuddyX Pro uses scheme-scoped color keys (the active color scheme plus buddyx_accent_color) and BuddyX Free uses a flat buddyx_primary_color key; the integration reads whichever applies. The resolved color is only injected when a WP Career Board stylesheet is actually on the page.

Developers can override or disable the resolved color with the wcb_theme_primary_color filter. Return an empty string to turn the override off entirely:

add_filter( 'wcb_theme_primary_color', '__return_empty_string' );

#OpenToWork Badge

On BuddyX Pro member profiles, WP Career Board adds an "#OpenToWork" badge next to the member name (via the buddyx_pro_after_member_name hook) for any candidate whose _wcb_open_to_work user meta is set. This badge surfaces a candidate's job-seeking status to the rest of the community. The badge appears only when that meta value is present on the member.

Compatibility Stylesheet

WP Career Board enqueues buddyx-compat.css on:

  • Any WP Career Board single post (wcb_job, wcb_application, wcb_company, wcb_resume)
  • Any WP Career Board post-type archive
  • Any WP Career Board taxonomy archive (category, job type, tag, location, experience)
  • Any page or post whose content embeds a wp-career-board/* or wcb/* block

BuddyPress with BuddyX

If you also run BuddyPress alongside BuddyX or BuddyX Pro, WP Career Board's BuddyPress integration adds member types and a job-posted activity item on top of the theme styling. See BuddyPress Integration for details.

Customizing the Design

All WP Career Board styles use the .wcb-* CSS class namespace and are driven by --wcb-* CSS variables. You can override any style by adding custom CSS to your BuddyX child theme or via Appearance > Customize > Additional CSS. Because the plugin is token-driven, re-mapping a --wcb-* variable restyles every block at once.

Reign Theme Integration

WP Career Board includes built-in support for the Reign theme by Wbcom Designs. When Reign is active, the job board uses Reign-tuned page templates, adds its links to Reign's navigation, exposes a Customizer color control, and inherits Reign's accent color.

What You Get

  • A Reign-compatible single job template for wcb_job posts
  • A Reign-compatible archive template for the jobs post-type archive
  • A Customizer color control under a dedicated "WP Career Board" section
  • WP Career Board links added to Reign's navigation (Browse Jobs, plus role-aware Employer Dashboard and My Applications)
  • An accent-color bridge that maps Reign's accent color onto WP Career Board's primary color
  • A compatibility stylesheet (reign-compat.css) loaded on every WP Career Board page

Requirements

  • Reign theme active (template slug reign-theme)
  • WP Career Board 1.4.3

The integration is selected by the active theme's template slug and boots automatically on after_setup_theme.

Setup

Activate Reign and WP Career Board. No additional settings are required; the integration activates automatically when Reign is the active theme.

Reign Customizer Control

With the integration active, Appearance > Customize shows a "WP Career Board" section. It contains a single control:

  • Primary Color - a color picker (default #4f46e5) that sets the job board's primary accent color to match your Reign theme.

This is the only Customizer control the Reign integration registers. Other styling is handled by the compatibility stylesheet and the accent-color bridge described below.

Accent Color Bridge

WP Career Board reads Reign's accent color from the Customizer and injects it as the plugin's --wcb-primary color so buttons, links, and highlights match the theme. Reign stores the accent color per color scheme (the active scheme plus reign_accent_color), with a fallback to the legacy single-key setting; the integration reads whichever is set. The color is only injected when a WP Career Board stylesheet is actually on the page.

Developers can override or disable the resolved color with the wcb_theme_primary_color filter. Return an empty string to turn the override off:

add_filter( 'wcb_theme_primary_color', '__return_empty_string' );

The integration appends WP Career Board links to Reign's navigation through the reign_nav_items filter:

  • Browse Jobs - always shown; links to your configured Find Jobs page, or /jobs/ if no page is set
  • Employer Dashboard - shown only to users who can post jobs; links to the configured Employer Dashboard page
  • My Applications - shown only to users who can apply to jobs; links to the configured Candidate Dashboard page

The Employer Dashboard and My Applications links are gated by the WP Career Board abilities wcb/post-jobs and wcb/apply-jobs, so each member sees only the links relevant to their role.

Compatibility Stylesheet

WP Career Board enqueues reign-compat.css (after Reign's main stylesheet) on:

  • Any WP Career Board single post (wcb_job, wcb_application, wcb_company, wcb_resume)
  • Any WP Career Board post-type archive
  • Any WP Career Board taxonomy archive (category, job type, tag, location, experience)
  • Any page or post whose content embeds a wp-career-board/* or wcb/* block

The stylesheet is token-driven and follows Reign's dark mode, so WP Career Board components re-color cleanly when Reign's dark mode is active.

Reign Add-Ons Compatibility

WP Career Board works alongside Reign's add-ons (such as the BuddyPress and LearnDash add-ons). Running those add-ons does not affect the job board. If you run the BuddyPress add-on, WP Career Board's own BuddyPress integration also applies; see BuddyPress Integration.

Custom CSS

Add overrides to your Reign child theme or via Appearance > Customize > Additional CSS. All WP Career Board styles use the .wcb-* prefix and --wcb-* CSS variables, so re-mapping a single variable restyles every block.

Tutorials

End-to-end walkthroughs for common job-board scenarios.

Your First Day as a Site Owner

A complete walkthrough from "I just installed the plugin" to "my first employer posted their first job and a candidate applied." Plan ~60-90 minutes for a thorough run. If you want to skim, the section headings below let you jump.

What you'll have at the end

  • A working job board at /find-jobs/ and /companies/ (a public /find-candidates/ directory is a Pro feature).
  • One employer account that can post jobs.
  • One candidate account that can apply.
  • Email notifications wired and tested.
  • A real test job published and a test application submitted.

Before you start

You need:

  • WordPress 6.9+ on PHP 8.1+ (the plugin checks this on activation).
  • An admin account on the site.
  • The ability to send email from the site (SMTP plugin, host SMTP, or the site already sending email reliably).
  • A theme that doesn't aggressively override .entry-content styles. Most modern themes work; some opinionated ones (Astra Pro, certain GeneratePress configs) need a custom CSS sweep - that's covered later.

If you want to test Pro features (AI, advanced credits, application pipeline, multi-board), install Pro too. The flow below assumes Free-only first, since Pro adds onto the same foundation.

Step 1 - Install

  1. Plugins → Add New → Upload Plugin. Pick the wp-career-board.zip you downloaded.
  2. Activate. The plugin spins up:
    • 3 database tables (jobs aren't a table - they're a CPT). Free creates its own tables; the credit ledger is a Pro table, not a Free one.
    • 3 custom roles: Employer, Candidate, and Job Moderator (the internal slug for Job Moderator stays wcb_board_moderator for back-compat). Banning an employer is a flag on the account, not a separate role.
    • 13 custom capabilities (#capabilities-and-roles-wcb)).
    • Five CPTs: wcb_job, wcb_company, wcb_application, wcb_resume, and the admin-only wcb_board.
  3. The Setup Wizard launches automatically. Don't dismiss it - walk it.

If you can't see the Setup Wizard, navigate to WP Admin → Career Board → Setup.

Step 2 - Walk the Setup Wizard

The wizard has two steps:

  1. Create Pages - the wizard creates the pages your board needs and maps them in Settings. The pages created are:

    • Find Jobs (search + filters + listings).
    • Companies (the company directory).
    • Employer Registration (sign-up form for new employers).
    • Employer Dashboard (includes Post a Job).
    • Candidate Dashboard (includes the resume builder and account settings).
    • Post a Job (the standalone job form).

    If a matching page already exists (it already contains the relevant Career Board block), the wizard reuses it instead of creating a duplicate.

  2. Sample Data - optionally install demo companies and jobs so the board isn't empty while you test. You can remove the sample data later from Career Board → Settings → Import without re-running the wizard.

There is no "what's your board for / who can post / how are postings paid for" questionnaire - those choices live in Career Board → Settings (Job Listings, Pages, Notifications, Emails) and you set them after the wizard.

Finish the wizard. You land on the Career Board settings screen.

Step 3 - Test email sending

Career Board sends nine transactional emails covering the application and job lifecycle: application confirmation (to the candidate), application received (to the employer/admin), application status changed, guest application, deadline reminder, job approved, job pending review, job rejected, and job expired. It does not send its own welcome, email-verification, or password-reset emails - those are handled by WordPress core. If your site can't send email, everything downstream breaks silently.

  1. Career Board → Settings → Emails. Each template row has a Send test button that emails the current admin a preview. Click it on any template.
  2. If you receive it within 30 seconds: green light, move on.
  3. If you don't: install WP Mail SMTP or Fluent SMTP, configure your provider (SendGrid, Mailgun, Postmark, Amazon SES, your host's SMTP), and retest.

This is the single most-overlooked step. Customers report "no applications coming in" - 70% of the time it's "applications came in, the email failed, employer never knew." Fix this on day one.

Step 4 - Set up email sender details

Career Board → Settings → Notifications. This tab holds the three sender settings:

  • From Name - usually your site name, not "WordPress." Defaults to your site name.
  • From Email - must match your sending domain (DMARC / DKIM / SPF). If your site is example.com, the from email should be noreply@example.com or similar. Defaults to the site admin email.
  • Admin Notification Email - where new-application alerts go when the posting employer hasn't set a custom address. Defaults to the site admin email.

The individual email templates (application received, application status changed, job approved, etc.) and their enable/disable toggles live on the separate Emails tab. Open each there to review the copy, toggle it on or off, and send yourself a test.

  • Application status changed - to the candidate. Keep enabled. This is the single most important candidate touchpoint after submission.

The plugin created the pages but didn't wire your menu.

  1. Appearance → Menus.
  2. Add: Find Jobs, Companies, Candidate Dashboard, Employer Dashboard, Post a Job. (A public Find Candidates directory is a Pro feature - add it only if Pro is installed.)
  3. The Employer Dashboard / Post a Job links can be in the menu OR accessible only via the employer dashboard once they log in - your choice based on whether employers self-register or you onboard them manually.
  4. Save.

Step 6 - Create your first test employer

Don't post a job from your admin account - that hides bugs. Create an actual employer and test the flow.

  1. Open a private window so you stay logged in as admin in the main browser.
  2. Visit /employer-registration/ (or whatever you mapped the employer-registration page to).
  3. Register with a real email you can check (e.g. your-name+test@gmail.com). The account is created with the Employer role.
  4. Log in as that employer (registration uses the standard WordPress account flow; Career Board does not send a separate welcome email).

Step 7 - Post the first test job

Still as the test employer:

  1. Click Post a Job from the employer dashboard.
  2. Fill in:
    • Title: "Test Job - Senior Frontend Engineer"
    • Description: a paragraph or two.
    • Category: any (or create one inline).
    • Location: any city.
    • Type: Full-time.
    • Application: leave as "Apply through this site" (not "External URL"). External-URL testing comes later.
  3. Submit.

If you set the posting cost to free, the job goes straight to Published. If you set "requires admin approval," it sits at Pending Review - go back to your admin window and approve it from WP Admin → Career Board → Jobs.

The same Jobs screen is also where you handle reported listings: when a logged-in visitor reports a job (scam, spam, expired, misleading, or offensive), a Flagged filter appears at the top of the list. Open it, review the flagged job and the reasons in the Flags column, then either Dismiss flag (the listing is fine) or Unpublish (the listing is bad) from the row or bulk actions.

Verify the job appears on /find-jobs/. If it doesn't:

  • Check the job's status (Published, not Draft).
  • Check the deadline isn't in the past.
  • Check your theme isn't redirecting /find-jobs/ somewhere.

Step 8 - Create your first test candidate

  1. Private window (or a different browser / incognito).
  2. There is no separate candidate-registration page. Open the Candidate Dashboard while logged out - it shows a Log in button that links to the standard WordPress login/registration screen. Register a normal WordPress account there.
  3. Log in. By default any logged-in member can use the candidate experience (apply, save jobs, build a resume) without a dedicated Candidate role. If you turned on Settings → Job Listings → Require Candidate Role, assign the Candidate role to the account first.
  4. Fill in profile: name, headline ("Senior Frontend Engineer"), skills, location.
  5. Upload a resume PDF (any sample resume works).

Step 9 - Apply to the test job

As the candidate:

  1. Open /find-jobs/ from the candidate's logged-in browser.
  2. Click the test job.
  3. Click Apply.
  4. The application form pre-fills from the candidate's profile + resume.
  5. Add a cover-letter paragraph.
  6. Submit.

You should see a "thanks - application submitted" confirmation.

Step 10 - Verify the employer side

Back in the employer window:

  1. Employer Dashboard → Applications. The test application should be visible.
  2. Click into the application. The candidate's resume should be attached and downloadable.
  3. Email check - did the new-application email arrive at the employer's inbox? If not, return to Step 3 and fix email sending.
  4. Move the application's status to "Reviewing." Save.
  5. Candidate email check - did the candidate receive a "your application status changed" email? If not, status-change notifications are off - re-check Settings → Notifications.
  6. Move the application to "Shortlisted," then "Hired." Each one fires an email to the candidate.

Step 11 - Verify the candidate dashboard

Candidate window:

  1. Candidate Dashboard → My Applications.
  2. The test application should show status "Hired."
  3. Saved Jobs - bookmark another job from /find-jobs/. Confirm it appears here.
  4. Profile - verify the profile is editable and changes save.

Step 12 - Clean up your test data

Once you're satisfied:

  1. Delete the test job from WP Admin → Career Board → Jobs.
  2. Delete the test application from WP Admin → Career Board → Applications.
  3. Delete the test candidate account from WP Admin → Users.
  4. Delete the test employer account.

Or keep them and move them to a "test" status so you can iterate. Up to you.

What's next

You have a working board. Now you'd usually pick a direction:

Common day-one mistakes to avoid

  • Skipping the email test. Everything breaks silently if email doesn't send. Always test before you announce the board.
  • Posting jobs from the admin account. Your admin sees everything and skips role gates. Always test as a real employer / candidate.
  • Skipping the deadline. Newly posted jobs default to the listing lifetime set under Settings → Job Listings → Default listing lifetime (days) (default 30, range 1-365). A job is moved to the expired status by the daily expiry cron once it passes its deadline.
  • Not wiring the menu. Employers and candidates can't navigate if the menu doesn't link to dashboards. Easy to forget; users notice immediately.
  • Forgetting Pro's license activation. If you also installed Pro, activate the license under Settings → License. The license drives automatic updates only - Pro features keep working without it, but you won't receive update notifications until it is activated.

Employer End-to-End: Hiring with WP Career Board

A complete walkthrough of one hiring round from the employer's perspective: register, set up your company, post the role, review applicants, hire, and close out. This is what you'd hand to a new employer joining your board.

Free flow throughout. Pro-only steps are flagged inline.

What a typical hiring round looks like

Phase Time What you do
Setup Day 0 Register, set up company profile, buy credits if needed
Post Day 0 Draft the role, publish
Promote Day 0-3 Share on socials, internal channels
Review Day 3-14 Read applications, shortlist, interview
Decision Day 14-21 Make offers, mark hired, close the role
Close out Day 21+ Archive the role, manage company profile for next round

Step 1 - Register as an employer

Most boards have a public registration link. Look for one of these:

  • A button on the main job board (/find-jobs/) saying "Post a Job."
  • A link in the site menu to "Employers" or "Hire Talent."
  • A direct URL like /employer-registration/.

If you can't find it, your site admin may not have wired the link. Email them - registration is open but unlinked.

Fill in:

  • Your name and email.
  • A password (or a magic-link if the site uses that).
  • Your company name (used to create your company profile).
  • Optional: phone, role at the company.

You'll get a welcome email. Some sites require you to verify your email by clicking the link before you can post - if so, do that first. Then log in.

Step 2 - Complete your company profile

You're now in the Employer Dashboard. Before posting your first job, complete the company profile - applicants see it on every job.

Employer Dashboard → Company.

  • Logo - square or rectangular, at least 200×200, max 2 MB. PNG / JPG. Most boards display 120-200 px.
  • Banner - optional, 1200×400 or similar wide format.
  • Tagline - one sentence (under 100 chars). "Building open source developer tools" is good; "We are a leading provider of innovative solutions" is filler.
  • About - two or three paragraphs. What you do, who you serve, what's the team like. Specifics beat marketing copy.
  • Website - full URL including https://.
  • Locations - at least one city. Multi-location companies can list several.
  • Size - 1-10, 11-50, 51-200, etc. Helps candidates pre-filter.
  • Founded - year. Optional but adds trust signal.
  • Industry - pick the closest match.

Save. Open your company in a private window - you should see a public company page at /company/your-slug/. If it looks empty or wrong, go back and fix.

Step 3 - Acquire posting credits (if your board uses them)

If posting is free on this board, skip this step.

Credit-based posting requires WP Career Board Pro. Free posts are always free; the credit balance, ledger, and checkout flow ship in Pro (powered by the Wbcom Credits SDK). If the board uses credits:

  1. Employer Dashboard. Your current credit balance shows on the overview stat cards.
  2. When a board has a per-post credit cost and your balance is too low, the job form shows a Buy Credits link. (The link only appears when the site owner has configured a purchase URL via the wcb_credit_purchase_url filter / Pro settings.)
  3. Complete the checkout your site owner set up.
  4. After payment, your balance updates and the post deducts the required credits.

If your balance doesn't update:

  • Refresh the dashboard.
  • Confirm the payment completed on whatever checkout your site uses.
  • Contact the site admin if it still doesn't show.

Step 4 - Draft and post your first job

Employer Dashboard → Post a Job.

Fill the basic info

  • Title - write the title a candidate would search for. "Senior Frontend Engineer" beats "Software Engineer III" beats "Code Wizard." Be specific without being clever.
  • Company - auto-filled from your profile. Verify it's right.
  • Job type - Full-time / Part-time / Contract / Internship / Temporary.
  • Category - one or more. Don't dump everything in "Other."
  • Location - city, state, country. If remote, set both a "Remote" flag AND a primary city (helps with time-zone matching).
  • Deadline / Apply by - the date the listing expires. Default 30 days from posting. Leave blank for "until filled" if your board supports it.

Write the description

The description is the single most important thing about the listing. A few principles:

  • Open with what the role is, not what your company does. A candidate skims this in 8 seconds - anchor them in the role first.
  • List 5-8 responsibilities as bullets.
  • List 4-6 requirements as bullets. Split nice-to-have from must- have if relevant.
  • Be honest about expectations. Time zones, on-call, travel, in-office days - say it up front, save time on both sides.
  • Salary range. If your jurisdiction requires posting salary (NYC, parts of EU, California for certain roles), include it. Even where not required, posting a range improves application quality dramatically.
  • About us / why work here - last, three or four bullets max. Don't repeat the company profile.

Pro tip: if you have Pro installed and AI Description Writer enabled, you can paste 4-6 key bullets and click Generate with AI. Always edit the output - it's a starting point, not a final draft. See ../ai-features/04-employer-ai-features.md.

Application settings

The job form has two optional apply-routing fields. Leave both blank to use the on-site flow:

  • On-site (default) - leave the Apply URL and Apply Email fields blank. Applications come into the Employer Dashboard and run through Career Board's email + status tracking.
  • Apply URL - an external URL. Candidates click out to your applicant tracking system (Greenhouse, Lever, Workable, etc.). When set, the single-job page routes Apply Now to this URL.
  • Apply Email - applicants send straight to this address. When set, the single-job page surfaces the apply email.

If you're new to the board, leave both blank and use the on-site flow. It's the only way Career Board's email + status tracking + AI scoring (Pro) all work together.

Click Submit Job.

Step 5 - Wait for approval (if applicable)

Some boards require admin approval for new postings. If yours does:

  • Status reads Pending Review.
  • Site admin gets an email + admin notice.
  • Approval typically arrives within 24 hours on a moderated board.

Once approved (or immediately, on auto-approve boards), status flips to Published and the job goes live at /job/your-job-slug/.

If it's been more than 48 hours with no movement, follow up with the site admin - sometimes the approval queue gets missed.

Step 6 - Promote the listing

Posting alone gets you maybe 5% of the applicants you should get. Promotion gets you the other 95%.

  • Share the URL on LinkedIn, Twitter, your company's Slack / Discord, internal company channels.
  • Set up a job alert so candidates who match the criteria get notified automatically - if the board has alerts enabled, candidates do this on their side.
  • Cross-post to one or two niche boards. Hacker News Who's Hiring, WeWorkRemotely, a Slack jobs channel, etc. Career Board exposes an enriched RSS feed at /jobs/feed/ that some aggregators consume automatically (it carries company, salary, location, type, category, tags, experience, deadline, and apply URL).

Step 7 - Watch applications come in

Employer Dashboard → Applications.

Each application shows:

  • Candidate name and current role / headline.
  • Submitted date.
  • Status (defaults to "Submitted").
  • Resume download link.
  • Cover letter / answers to any custom questions you added.
  • (Pro) AI Fit Score 0-100 + one-line reason.

Click into an application to see the full detail and the candidate's public profile (if they made it public).

You'll get an email per application (as long as the admin has notifications wired correctly). If applications are arriving faster than you can read them in real time, set yourself a 9 AM / 4 PM block to triage rather than reacting to each email.

Step 8 - Triage applications

A simple triage pass:

  1. Status filter to "Submitted." Hides applications you've already triaged.
  2. Read each in 30-60 seconds. Focus on resume + cover letter. Don't read every detail yet.
  3. Move to "Reviewing" if you'd consider talking to them - even if not yet sure.
  4. Move to "Rejected" if it's clearly not a fit (wrong role, no right-to-work, etc.).
  5. Move to "Shortlisted" if it's an obvious "yes, let's interview."

Each status move fires the "application status changed" email to the candidate (good - keeps them informed). You can edit that template (and every other email) in WP Admin → Career Board → Settings → Emails (admin-only).

Pro tip: if AI Fit Score is enabled, sort by it. Read top 10 first. Don't auto-reject by score - see ../ai-features/04-employer-ai-features.md.

Step 9 - Interview shortlisted candidates

The board doesn't run interviews - you do that externally. The board helps you stay organised:

  • Move applications through the five statuses (Submitted, Reviewing, Shortlisted, Hired, Rejected) to track where each candidate is.
  • (Pro) Use the List / Board toggle on the Applications view. The Board is a Kanban that groups applicants into status columns (Submitted, Reviewing, Shortlisted, Hired, Rejected); drag a card to change status, and the list, board, status emails, and AI ranking stay in sync.
  • (Pro) Use the Application Pipeline module and the Field Builder to add custom application fields and tags.

Step 10 - Make a decision

When you've picked your candidate:

  1. Move to "Hired." Email fires to the candidate.
  2. Email the candidate directly with the offer - the board's "Hired" email is informational, not the offer letter. Always send the formal offer separately with details.
  3. Reject the rest. Move remaining shortlist candidates to "Rejected" with a courteous message. Some employers send a short personal email instead of relying on the template - your call.

Step 11 - Close out the role

Once filled:

  1. Close the job from Employer Dashboard → My Jobs (the Close action). This takes it out of the public listing while your existing applications stay visible to you. (There is no separate "Filled" status; closing or letting the deadline pass removes it from the board.)
  2. (Optional) Export applications to CSV. The bulk CSV export lives on the admin side: WP Admin → Career Board → Applications, select the rows, and use the export action. The spreadsheet includes applicant name, email, job, status, applied date, cover letter, and resume URL.
  3. (Optional) Update your company profile with the new hire's role / team if you list staff.
  4. Refresh credits (Pro) - top up if you have another role coming up.

Step 12 - Build a candidate bench (Pro)

If you've installed Pro, the Find Candidates feature lets you search the candidate directory directly:

  • Employer Dashboard → Find Candidates.
  • Search by skill, location, headline, "Open to Work" flag.
  • Save candidates to a private list to revisit when a new role opens.
  • Send a short message asking if they'd be interested in your next role.

Free doesn't include outbound candidate search - only inbound (i.e. candidates apply to you).

Common employer mistakes

  • Posting and walking away. The first 48 hours after posting is when most quality applications come in. Be ready to review.
  • No salary range. You're competing for attention with listings that do disclose. Most candidates filter you out without one.
  • Slow status updates. Candidates check the dashboard for status changes. A week of "Submitted" feels like a no - they assume rejection. Move to "Reviewing" within 48 hours even if you haven't read them fully yet.
  • Rejecting silently. Sending a "Rejected" status with the default email is better than ghosting. Candidates remember employers who closed the loop and apply again for future roles.
  • Posting the same job twice. Confusing for candidates. Edit and republish the existing posting instead of creating a duplicate.

What you should walk away with

After one full hiring round you'll know:

  • How long applications take to start arriving on your specific board.
  • The ratio of applications to quality matches (helps you decide whether to widen or narrow next time).
  • What questions you wish you'd added to the application form (Pro: field builder).
  • Whether the board's defaults work for you or you need to adjust (notification settings, default deadline, etc.).

Where to go next

Candidate End-to-End: Finding a Job with WP Career Board

A complete walkthrough from "I just landed on the board" to "I got hired." This is what you'd hand to a candidate explaining how the site actually works.

Free flow throughout. Pro-only features are flagged inline.

What a typical job search looks like

Phase Time What you do
Discover Hour 0 Browse the board, get a feel for what's listed
Set up Day 0 Register, build profile, upload resume
Search Day 0 onward Find roles that fit, save them, set alerts
Apply Day 0-7 Apply to a curated shortlist, not 50 random jobs
Track Day 0-30 Watch status updates, withdraw if not interested anymore
Outcome Day 7-60 Get hired, or learn from the rejections

Step 1 - Browse before you register

Don't register first. Look around.

  1. Open /find-jobs/ on the board.
  2. Use the filters: category, location, type, remote-friendly, and the salary range slider (a Free feature on the Find Jobs page).
  3. Read 3-5 listings that look interesting. You're calibrating: what roles does this board actually have? Are they your level? Right industry?
  4. Open a couple of company profiles to see what employers look like.

If nothing catches your eye, the board may not be the right fit for you - better to know now than after building a profile.

Step 2 - Register

When you've found roles worth applying to:

  1. Open the Candidate Dashboard while logged out and click Log in - it links to the site's standard WordPress login/registration screen. (There is no separate candidate-registration page.) You can also apply as a guest from a job's apply form without an account at all.
  2. Register a normal account (name, email, password).
  3. Log in. On most boards any logged-in member can use the candidate experience straight away. If the site owner enabled "Require Candidate Role," they assign you the Candidate role first.

Step 3 - Build your candidate profile

Candidate Dashboard → Profile.

Don't skip this - applications that come from a fully-built profile look more credible than ones from a blank account.

Free profile fields

The Free candidate profile is intentionally lightweight:

  • Email - your contact address.
  • Phone - optional contact number.
  • Location - city and country. If you're open to relocating, say so in the bio.
  • Bio / About Me - a rich-text editor. Two or three paragraphs: what you've built, what you're looking for, what you're not looking for. Be specific.

Your display name, email, and password are edited under Candidate Dashboard → Settings (Account Settings).

Richer profile and resume fields (Pro)

A structured profile - headline, skills, work experience, education, languages, links, a profile photo, an "Open to Work" flag, and a public candidate profile URL discoverable in the employer candidate directory - ships with WP Career Board Pro (the resume builder and candidate directory). If the board runs Pro, fill those in too; in Free your applications carry your bio plus your uploaded resume.

Step 4 - Your resume

In Free, you attach a resume file to each application from the apply panel - there is no resume stored on the dashboard. The site owner sets whether the resume is required and the maximum file size (Settings → Job Listings → Application Resume File Size, default 5 MB, range 1-20 MB).

  • PDF preferred. Word docs work too. Accepted formats: PDF, DOC, DOCX.
  • Keep it small. Most resumes are well under the default 5 MB cap.

Pro: the My Resumes tab and the Resume Builder (the "Edit Resume" view) are Pro features. With Pro you build a resume on the dashboard, pick a saved resume in one tap when applying (the PDF is generated and attached automatically), and - with an AI provider - auto-fill the builder from an uploaded resume. See ../ai-features/03-candidate-ai-features.md.

Step 5 - Set up job alerts (Pro)

Job alerts require WP Career Board Pro. In Free you check the board yourself (or bookmark roles, Step 6). When Pro is installed, the Job Alerts tab in the Candidate Dashboard becomes active:

  1. Candidate Dashboard → Job Alerts → New Alert.
  2. Keywords: "senior frontend" or "data engineer" - be specific.
  3. Location: city / country / "Remote."
  4. Frequency: daily for active job search, weekly if you're casually browsing.
  5. Save.

You'll get an email when matching jobs are posted. Set up 2-3 alerts covering your search variations.

Pro features: semantic matching widens alerts beyond exact keyword match (a "backend" alert will surface "server-side" postings) when an embedding provider is configured.

Step 6 - Search and shortlist

Once your profile is good, the rhythm is:

  1. Check the board daily / weekly (or your Pro alerts if Pro is on).
  2. Read the listings that match. Don't apply yet.
  3. Bookmark the interesting ones - click the bookmark icon. They land in Candidate Dashboard → Saved Jobs.
  4. Read the company profile for each. If the company seems wrong for you, unbookmark.
  5. Apply only to your shortlist - usually 3-8 per week is the right pace. Mass-applying to 50 listings is counterproductive.

Pro tip: if AI Chat Search is on the board, try natural language queries:

Senior React role, remote-friendly, US time zones, $130k+

The results rank by relevance, not by date. Helpful when keyword search isn't finding the right roles.

Spot a bad listing? Report it

If a listing looks like a scam, spam, an expired/already-filled role, or is misleading or offensive, you can flag it for the site's moderators.

  1. Open the job page while logged in (you can't report your own listing).
  2. Click Report this job.
  3. Pick a reason: Scam or fraudulent, Spam or advertisement, Expired or already filled, Inaccurate or misleading, or Offensive or inappropriate.
  4. Submit. You'll see a short confirmation.

Reporting is one click per person per job - if you report the same job again nothing changes. A moderator reviews flagged jobs and either dismisses the flag (the listing was fine) or unpublishes the job (the listing was bad). You won't get a personal reply, but you've done your part to keep the board clean.

Step 7 - Apply

For each shortlisted job:

  1. Click Apply on the job page.
  2. The form pre-fills your contact details from your account. Verify it's right.
  3. Cover letter - write 4-6 sentences specific to this role. Don't paste a generic letter.
  4. Resume - upload a resume file (or, with Pro, pick a saved resume; your most recent one is pre-selected).
  5. Submit.

You'll get a confirmation email. The application is now visible in Candidate Dashboard → My Applications.

What to write in a cover letter (paragraph by paragraph)

If the application form has a "Cover letter" textarea (most do):

  • Paragraph 1: why this specific job. Name the role, name something specific about the company.
  • Paragraph 2: why you. One or two concrete examples from your background that match what the role needs.
  • Paragraph 3: logistics if relevant. Notice period, location, start-date constraints.

Don't:

  • Restate your resume.
  • Apologise for any gap.
  • Use "To Whom It May Concern" - the employer's name is usually on the company profile.

Step 8 - Track applications

Candidate Dashboard → My Applications.

Each row shows:

  • Job title + company.
  • Status - Submitted, Reviewing, Shortlisted, Hired, Rejected, Withdrawn, Job Removed.
  • Submitted date + last update date.

When the employer changes your status, you get an email and the dashboard updates.

What each status means

  • Submitted - they have it; no decision yet. Most applications stay here for several days before the employer looks.
  • Reviewing - they've opened it. Activity, but no decision yet.
  • Shortlisted - under serious consideration. Expect interview outreach.
  • Hired - congratulations. Confirm details with the employer outside the platform.
  • Rejected - not moving forward. The application is closed.
  • Withdrawn - you (or the system) pulled the application out.
  • Job Removed - the employer or admin deleted the job posting while your application was in flight. Your application is preserved in your history.

What to do if your application sits at "Submitted" forever

  • Most employers take 1-2 weeks to triage. Be patient.
  • After 3 weeks, you can email the employer directly through their company profile (if they listed contact) for a quick "any update?" ping. Once is fine - don't repeat.
  • After 4 weeks with no movement, assume soft rejection. Move on.

Step 9 - Withdraw if your situation changes

If you got an offer elsewhere or you're no longer interested:

  1. My Applications → click the role → Withdraw.
  2. Confirm.
  3. The employer is notified.

This frees up your "I've already applied" status - if a duplicate of the role comes up in 3 months, you can re-apply.

Step 10 - Manage saved jobs and alerts over time

Your search will shift. Update accordingly:

  • Saved Jobs - periodically clear out ones that expired or you no longer want.
  • Job Alerts (Pro) - if Pro is installed, adjust keywords when your alerts get too noisy or too quiet.
  • "Open to Work" flag (Pro) - the candidate directory and the Open-to-Work flag are Pro features. If the board runs Pro, turn the flag off once you accept an offer.

Step 11 - Delete your account when you're done

If you've landed a job and don't want lingering data:

  1. Candidate Dashboard → Settings. Use Export my data to request a copy, or Delete my account to request erasure.
  2. Both actions send a confirmation email to your registered address. Click the link in the email to confirm.
  3. The request enters WordPress's standard privacy queue and is processed by the site administrator. On erasure your applications and resumes are deleted and your account is removed.

This runs through WordPress's built-in privacy request flow, so it is GDPR / privacy compliant. Erasure is irreversible - keep any data you want before confirming.

Common candidate mistakes

  • Empty profile, single application. Employers click through to your profile when reviewing. If it's empty, the application looks half-hearted regardless of resume quality.
  • One resume, 50 applications. Tailor at least the cover letter per role. Generic = visible.
  • Following up too aggressively. One polite ping after 3 weeks is fine. Daily emails to the employer hurt your candidacy.
  • Ignoring rejection emails. Read them - sometimes employers include genuinely useful feedback or invite you to apply for a future role.
  • Forgetting to turn off "Open to Work" after landing a job (Pro). On Pro boards your new employer's HR might be browsing the candidate directory and notice.

Where to go next

Monetizing Your Board

How to make money from your job board. Covers the four models WP Career Board supports, when each one is the right call, and the mechanics of setting each up.

Free vs Pro. WP Career Board Free supports one monetization model: free postings. Every paid model below - pay-per-post, credit packages, and subscriptions - requires WP Career Board Pro. Pro ships the credit ledger (the wcb_credit_ledger table) and the Wbcom Credits SDK, which provides the WooCommerce, WooCommerce Subscriptions, WooCommerce Memberships, Paid Memberships Pro, and MemberPress adapters. The credit fields you see in Free's job form (cost, balance, Buy Credits link) are filter-driven stubs that default to free/zero until Pro fills them in. The admin screens this page mentions for credits, mappings, and the ledger are Pro screens.

The four models

Model What employers pay for When it fits Setup complexity
Free Nothing - postings are free Niche communities, employer-branding boards, sites where the goal is engagement not revenue Trivial
Pay-per-post A flat fee per job listing Small to medium boards with predictable per-job value Low
Credits / packages Bundles of postings purchased upfront Recruiters or agencies who post multiple times per month - cheaper per-post when bought in bulk Medium
Subscriptions Recurring monthly / annual access for unlimited (or N) postings High-volume employers, boards positioned as "Indeed for niche X" Medium

You can also combine: free for one type of role (e.g. internships), paid for premium roles, with optional "featured" upgrades on top.

Model 1 - Free postings

The simplest model. Employers register and post without paying. You fund the board through:

  • Sponsorships - a banner ad slot on the home page (your theme), sponsored by a company that wants exposure.
  • Affiliate / commission - Career Board doesn't track placements; for affiliate, integrate manually or use a third-party tool.
  • Adjacent product / service - a paid plugin, a course, a recruiting service, etc. The job board drives traffic; you sell something else.

Setup

  1. WP Admin → Career Board → Settings → Job Listings.
  2. Posting cost: Free is the default - there is no per-post cost in the Free plugin, so there is nothing to set. (Per-post credit cost is a Pro feature.)
  3. Moderation: the Auto-Publish Jobs toggle controls this. It is OFF by default, so new postings sit at Pending Review until an admin approves them. For free boards keep it off - spammers love free boards. Turn it on only if you trust your posters.

When this is right

  • You have an existing audience (community, newsletter, etc.) and the board is a service for them, not a product itself.
  • Your goal is reach, not revenue.
  • Spam is manageable through moderation.

When this is wrong

  • You need cash flow from the board.
  • You don't have time to moderate a high-volume free queue.

Model 2 - Pay-per-post (Pro, WooCommerce-backed)

Each new job posting requires payment. This requires Pro and a checkout layer; WooCommerce is the most common choice.

Setup

  1. Install WooCommerce. Run its setup wizard. Configure payment gateways (Stripe / PayPal / etc.).
  2. Install Pro. Pay-per-post needs Pro's credit ledger and the Wbcom Credits SDK. (The license drives updates only; the credit feature works once Pro is installed.)
  3. Create a "Job Posting" WooCommerce product.
    • Type: Simple product.
    • Price: $29, $49, $99 - whatever your market bears.
    • Title: "Single Job Posting (30 days)."
  4. Map the product to a credit grant in the Pro Credits admin tab (WP Admin → Career Board → Settings → Credits → Credit Mappings).
    • Adapter: WooCommerce.
    • Product: the one you just created.
    • Credits granted: 1.
  5. Set a Credits Purchase URL in the same Credits tab, pointing at the WooCommerce product. The Buy Credits button only appears once both the mapping and the purchase URL are set.
  6. Set the per-board posting cost. Credit cost is configured per board (opt-in since Pro 1.3.0). Give the board employers post to a cost of 1 credit. Employers now need 1 credit to post a job there.

Flow from the employer's perspective

  1. Employer clicks Post a Job.
  2. Form shows: "You have 0 credits. Buy 1 credit to continue."
  3. They click Buy Credits, get redirected to WooCommerce checkout.
  4. After payment, credit lands on their account (via the ledger).
  5. Back on the form, the credit auto-deducts and the job posts.

When this is right

  • You want predictable per-job pricing.
  • Most employers post 1-3 jobs per year (one-off pricing makes sense).
  • You're early days and want to gauge demand before bundling.

Variations

  • Featured upgrade - separate WooCommerce product priced higher ($99 instead of $29). Map it to "Featured upgrade" consumer in Career Board. Employers can buy it during the post flow.
  • Tiered pricing - different products per category. Senior / executive postings cost more than entry-level. Map each to a different category at the credit-mapping level.

Model 3 - Credit packages (Pro)

Bulk pricing: employers buy 5 or 10 postings upfront at a discount.

Setup

  1. WooCommerce + Pro (same as Model 2).
  2. Create multiple WooCommerce products:
    • "1 Job Posting" - $49 - grants 1 credit.
    • "5 Job Postings" - $199 ($40/each) - grants 5 credits.
    • "10 Job Postings" - $349 ($35/each) - grants 10 credits.
  3. Map each to its credit grant in Settings → Credits → Credit Mappings.

Flow from the employer's perspective

  1. The employer sees their credit balance on the dashboard overview (and the Pro Credit Balance block) and clicks Buy Credits on the job form when their balance is too low.
  2. They see the packages you mapped.
  3. Pick a package, check out via WooCommerce.
  4. Credits land on their account. They post normally; each post on a paid board holds, then deducts, the board's credit cost.

When this is right

  • You have repeat employers (recruiters, agencies, staffing firms).
  • Volume discount is a real selling point.
  • You want a stable balance sheet - money upfront, postings spread over months.

Model 4 - Subscriptions (Pro)

Employers pay monthly or annually for unlimited (or capped) postings.

Setup options

The Wbcom Credits SDK bundled in Pro ships adapters for these membership / subscription back-ends:

Plugin Best for Setup
WooCommerce One-off product purchases Pro + WooCommerce adapter
WooCommerce Subscriptions Mature ecosystem, lots of payment-gateway support Pro + WooCommerce Subscriptions adapter
WooCommerce Memberships Membership tiers on top of WooCommerce Pro + WooCommerce Memberships adapter
Paid Memberships Pro Community + content-gating + jobs in one plan Pro + PMPro adapter
MemberPress More polished membership UX, but per-feature pricing adds up Pro + MemberPress adapter

(There is no Restrict Content Pro adapter; pick one of the back-ends above.)

Setup (PMPro example)

  1. Install PMPro. Configure your gateway.
  2. Create membership levels:
    • Starter - $49/month - 3 postings.
    • Pro - $199/month - unlimited postings.
    • Annual Pro - $1,990/year - unlimited postings (10-month pricing).
  3. In Settings → Credits → Credit Mappings, map each PMPro level to a credit grant:
    • Starter level → 3 credits per billing cycle.
    • Pro level → 999 credits per billing cycle (effectively unlimited).
  4. Credits auto-grant on subscription payment (via the PMPro adapter).

Flow from the employer's perspective

  1. Employer registers, picks a plan, completes subscription checkout.
  2. Credits land on their account immediately.
  3. Each billing cycle, credits refresh (subject to your "carry over unused?" policy - set this in the adapter mapping).
  4. Cancellation: subscription stops, no new credits, existing credits remain until expired or used.

When this is right

  • Your board has high-volume repeat employers.
  • You want recurring revenue, not one-time.
  • You're competing with general job boards on volume and need a business model that scales.

Combining models

Most real boards run a hybrid. Examples:

  • Free for non-profits, paid for everyone else. Filter the post-a-job form based on the user's role / membership level.
  • Free postings + paid Featured upgrade. Volume comes free, you monetize the employers who want visibility.
  • Free first posting as a trial, paid thereafter. Career Board doesn't ship this out of the box - you'd need a tiny custom plugin that grants 1 credit on first registration.

Pricing - what to actually charge

There's no universal right number, but anchors:

Board type Typical per-post price
Local / city-specific $10-$30
Niche tech (remote-friendly) $50-$200
Executive / specialty $200-$500
Internship / academic $0-$30 (often free)
Healthcare / regulated industry $100-$400

Featured upgrades typically cost 2-3× the standard price. Bundle discounts typically save 20-40% over individual purchase. Annual subscriptions typically price at 10× monthly (give 2 months free).

Start with the low end of the range. You can always raise later; lowering looks bad.

How the credit ledger handles refunds and disputes (Pro)

Pro's credit ledger is append-only. Every credit movement writes a row - top-up, hold, deduct, refund. Rows are never edited or deleted.

Refund flow:

  1. WooCommerce / PMPro / MemberPress issues the refund through its own checkout flow.
  2. The adapter detects the refund event and writes a refund ledger row.
  3. The employer's credit balance reduces by the refunded amount.
  4. If the employer already posted jobs against those refunded credits, the job posts stay live; the balance just reflects the refund.
  5. For disputes that don't go through the checkout (e.g. a bank chargeback handled externally), use the manual adjustment card at the bottom of Settings → Credits to write an offsetting row. There is no per-employer "Adjust" button and no separate ledger report screen - adjustments all happen from that one card.

Tracking revenue and renewals

  • WooCommerce → Reports for order revenue.
  • PMPro → Reports for subscription metrics (MRR, churn).
  • Career Board → Settings → Credits (Pro) shows the manual adjustment card with a user's current balance; the ledger itself is the append-only record behind the balance.
  • For deeper analytics, query the credit ledger table or your checkout plugin's reports - Career Board does not ship a built-in revenue dashboard.

Common monetization mistakes

  • Charging too much too early. A new board with no traffic gets zero postings if pricing matches Indeed. Start cheap, build a base, raise as you fill listings.
  • Hiding the price. Employers should see what postings cost before they register. A clear pricing page beats a maze.
  • No free option for testers. Many employers want to "try one posting" before committing to a package. Either offer a free first posting or a 7-day money-back guarantee.
  • Auto-cancelling paid jobs on subscription expiry. Confusing for both employers and candidates. Keep posted jobs live until their natural deadline; just stop new postings on expired subscriptions.
  • Not testing the buy flow. Always run a real $1 product end-to-end before going live. The ledger, the email, the credit grant, the post flow - they all need to land.

Where to go next

  • Pro's credit-system docs (credit-system/01-overview.md in the Pro docs) - full credit system, mappings, and refund reference.
  • 02-employer-end-to-end.md - the employer flow you're enabling.

Community Job Board with BuddyPress

If your site already runs a BuddyPress (or BuddyBoss) community, Career Board integrates so members can post jobs from their group, candidates can be discovered by their member profile, and applications can flow through the BuddyPress activity stream. This page walks through the setup and the design decisions.

When this combination makes sense

Common patterns:

  • Industry association - a community of professionals where each member's organisation occasionally hires. Jobs posted within member-only groups, not on a public board.
  • University alumni network - alumni hire other alumni; the board lives inside the alumni community.
  • Bootcamp / cohort community - graduates support each other's job search; the board is part of the cohort experience, not a public service.
  • Vertical industry community - e.g. a developer Slack-style community where a paid plan unlocks the job board area.

If you don't already run BuddyPress, you don't need it. Career Board works fine standalone.

Prerequisites

  • WordPress 6.9+, PHP 8.1+.
  • BuddyPress (or BuddyBoss equivalent).
  • WP Career Board Free or Pro. Free's BuddyPress integration is deliberately thin (see below); the community features in this guide - per-group boards, the group Jobs tab, member filters, activity broadcasts, and the BuddyPress notification bell - are Pro.
  • Groups component enabled in WP Admin → BuddyPress → Components.
  • Activity Streams component enabled if you want activity broadcasts.

What Free's BuddyPress integration actually does

Free's integration is limited to two things:

  • It registers employer and candidate BuddyPress member types and keeps them in sync with the Career Board roles.
  • It posts a single activity entry to the stream when a job is published ("[Member] posted a new job: [Title]"). This fires automatically and has no on/off setting in Free.

Everything else described below requires Pro.

Architecture: how Career Board and BuddyPress fit together

Career Board uses boards as a high-level container for jobs. A board can be:

  • Public - visible to everyone, jobs listed on /find-jobs/.
  • Tied to a BP group (Pro) - only group members see and can post to it.
  • Member-only - anyone logged in can see and post, no group required.

The mapping is:

BuddyPress Group "Frontend Engineers"
    └── Career Board: "Frontend Jobs" (group-tied board)
            ├── Job: "Senior React at Acme"
            ├── Job: "Frontend Lead at Beta"
            └── Job: "Junior Frontend at Gamma"

Members of the "Frontend Engineers" BP group see and can post to the "Frontend Jobs" board. Non-members don't see those listings.

Pro feature. The board-to-group mapping requires Pro's Multi-Board module. Free supports a single global board only.

Step 1 - Install and verify components

  1. Activate Career Board and BuddyPress in the order: BuddyPress first, then Career Board.
  2. BuddyPress → Components - confirm "Groups" and "Activity Streams" are enabled.
  3. The integration boots automatically when BuddyPress is active - there is no "Settings → Integrations" tab in Free to toggle. If the member types or activity entries don't appear, confirm BuddyPress loaded before Career Board (deactivate-reactivate Career Board after BP is on).

Step 2 - Map a BP group to a Career Board board (Pro)

For each BP group that should have its own job board:

  1. BP group → Manage → Career Board tab (the tab appears once Pro is on).
  2. Click Create board for this group. Set:
    • Board name - usually "Group Name Jobs."
    • Slug - auto-generated from the name; tweak if needed.
    • Default category - optional; jobs without an explicit category land here.
    • Posting cost - per-board credit cost. 0 if free.
    • Visibility - Group Members Only, Site Members, Public.
  3. Save.

A new board exists, ready to receive postings. Group members navigating to the group's Jobs tab see the listing.

Step 3 - Add a Jobs tab to each group

The Career Board integration registers a Jobs tab on each group automatically. To customise:

  1. BP group → Manage → Members → Visibility.
  2. The Jobs tab is visible to all group members by default. If you want it visible only to certain member types (e.g. "Verified employer"), filter via the standard BP group permissions or use the wcbp_board_visibility filter for fine-grained control.

To rename the tab (e.g. "Hiring" instead of "Jobs"), edit the BP group nav label or use the wcbp_group_jobs_nav_label filter.

Step 4 - Member profile and candidate directory (Pro)

The candidate directory, the public candidate profile, and the "Open to Work" flag are Pro features (Pro's BuddyPress member filters module surfaces candidates by their Career Board profile). Free registers the employer / candidate member types but does not add a "Current role" / "Open to Work" pair to BP profiles by itself.

In Free you can still use standard BuddyPress XProfile fields for extra candidate data; Pro's member filters read them when building the candidate directory.

Step 5 - Activity broadcasts

In Free, exactly one activity event fires - a "[Member] posted a new job: [Title]" entry when a job is published. It is always on and has no setting.

Pro adds the configurable broadcast set (job posted, application sent, hired, etc.) through its BuddyPress activity module. Application- and hire-side activity should stay off unless your privacy policy covers it - most job searches are private.

Step 6 - Notifications via BP (Pro)

The BuddyPress notification bell integration is a Pro module (notificationsbell). Once Pro is active it surfaces Career Board events - new application on your job, application status changed, new job in your group - in the BP bell in addition to the standard email. Free sends the emails but does not write BP bell notifications.

There is no "Settings → Notifications → Channels" toggle; the bell is driven by the Pro module rather than a per-channel setting.

Step 7 - Member directory filters (Pro)

Pro's BuddyPress member filters add Open to work and Hiring filter chips to the BuddyPress members directory (/members/), scoping it to candidates who set themselves open to work or to employers. This is a directory filter, not a permission gate.

There is no "Member Type Gating" settings screen. To restrict who can post or what a board shows, use the capability system (the Career Board roles) and the board/permission filters (for example wcb_board_options_for_employer). Member-type-specific logic is wired through code/filters rather than an admin mapping UI.

Step 8 - Test the integration end-to-end

The standard test path:

  1. Create two test BP user accounts: one "employer," one "candidate" / member.
  2. Add both to a BP group, then map that group to a Career Board board.
  3. As employer: post a job to that board from the group's Jobs tab. Confirm it appears on the group's Jobs listing.
  4. As candidate: navigate to the group's Jobs tab. See the listing. Apply.
  5. Back as employer: receive the application notification (email AND BP bell).
  6. Move through statuses. Candidate receives matching notifications.
  7. Verify: a non-member of the group navigating to /find-jobs/?wcb_board=group-frontend gets "not authorised" (or "redirect to login" depending on board visibility setting).

Common patterns

Pattern 1: closed community with multiple sub-boards

Run a paid community where membership unlocks job board access. Each sub-group has its own board.

  • PMPro / MemberPress + BP for the paywall.
  • Multi-Board (Pro) for per-group boards.
  • Job posting cost = 0 in credit settings (membership is the paywall, not per-post fees).

Pattern 2: open community, restricted hiring

Anyone can join the community and view jobs. Only verified employers can post.

  • BP open registration.
  • Career Board roles: candidate role auto-assigned on registration.
  • "Verified employer" role requires manual admin approval (or use the wcb_employer_default_role filter to set a "pending verification" state).

Pattern 3: alumni network

Members are organised by graduation year. Each year cohort has a group with its own job board.

  • BP groups named by year.
  • One board per year group.
  • Some boards public for cross-year networking, others private.

Troubleshooting

Jobs tab missing from BP group

  1. Career Board is active AND Pro is active. (Pro's license drives updates only - it never gates whether the Jobs tab appears.)
  2. The group is mapped to a board in Group Manage → Career Board.
  3. The current user has permission to see the tab (member of the group OR the board is set to "Site Members" / "Public").
  4. BuddyPress loaded before Career Board so the integration booted (the integration is automatic - there is no enable toggle).

Member sees jobs they shouldn't

Board visibility is set too permissively. Check:

  • Multi-Board → Boards - the board's "Visibility" field. Should be "Group Members Only" for group-tied boards.
  • Members listed in the group - make sure the user isn't in the group when they shouldn't be.

BP bell notification not firing on application (Pro)

  1. Pro is active (the notification bell is the Pro notificationsbell module; Free sends email only).
  2. The receiving user has BP notifications enabled in their account settings.
  3. The BP Notifications component is active.
  4. The custom component is registered with BuddyPress (Career Board notifications only show in the theme bell when registered via the bp_notifications_get_registered_components filter).

Activity stream missing the job-posted event

  1. The Activity Streams component is enabled in BP.
  2. The job actually reached Published status - Free's activity entry fires on publish (wcb_job_created for a published job). A job stuck at Pending Review won't post an activity entry yet.
  3. For the broader configurable broadcast set (applications, hires), confirm Pro is active - those are Pro's activity module, not Free.

Where to go next

Migrating from Another Job Board Plugin

If you already run a job board on WordPress with WP Job Manager, Simple Job Board, WP Jobster, or a similar plugin, you can migrate to WP Career Board without losing data or breaking your existing URLs. This page walks through the path.

Before you migrate - make these decisions

  1. Same URL structure or new one? Career Board registers its jobs CPT at the jobs slug, so single jobs live at /jobs/{slug}/ and the CPT archive is /jobs/. WP Job Manager defaults to /job/{slug}/ (singular), so even a WPJM migration needs a redirect from /job/... to /jobs/.... Set up redirects so the old URLs still work - covered below.

  2. Move applications and candidate accounts, or only jobs?

    • Jobs only is the fast migration: ~30 minutes.
    • Jobs + applications + candidate accounts is the slow migration: 1-3 hours, more variables.
  3. Hard cutover or soft?

    • Hard: deactivate the old plugin the moment Career Board is ready. URLs flip in one window.
    • Soft: run both plugins for a couple of weeks; the old plugin handles existing listings; new postings go through Career Board. Migrate old listings on a schedule.
  4. Same theme or new? If your old plugin had a heavily-customised template, your theme likely has overrides for it. Plan a quick visual QA after switching.

Migration paths by source plugin

From WP Job Manager (Astoundify / Automattic)

The most common migration, and the only built-in importer. WP Job Manager migration ships in Free - you do not need Pro for it.

Prerequisites:

  • WP Career Board (Free) installed and active.
  • Old WP Job Manager still active during the migration so its data is readable.

Path:

  1. WP Admin → Career Board → Import. The page shows a card for each importer and whether the source plugin is detected.
  2. WP Job Manager → Jobs. This migrates job_listing posts to wcb_job, carrying:
    • Company (post meta _company_name_wcb_company_name, logo included).
    • Categories (taxonomy job_listing_categorywcb_category).
    • Types (taxonomy job_listing_typewcb_job_type). Each migrated job is tagged with _wcb_migrated_source = wp-job-manager, so re-running the importer safely skips records already migrated.
  3. Run it. The importer works in batches and is idempotent (safe to run again).
  4. WP Job Manager → Resumes. A separate card on the same Import page migrates WPJM Resumes (resume CPT) into wcb_resume. (Resumes are a Pro feature, so this card is useful when Pro is active.)
  5. Verification: open /find-jobs/ (or the /jobs/ archive) in a new tab. You should see the old jobs. Note the new single-job URL is /jobs/{slug}/, so add a redirect from the old /job/{slug}/ (singular) pattern - see "Preserving URLs" below.
  6. Deactivate WP Job Manager when you're confident.
  7. Test apply flow as a candidate - the apply form is the most common breakage point.

What doesn't transfer automatically:

  • Bookmarks/saved jobs in WPJM - the data model is different; bookmarks reset.
  • Custom fields added through WPJM Field Editor - not mapped. Recreate them with Pro's Field Builder.

From other plugins (Simple Job Board, WP Jobster, custom CPTs)

There is no dedicated importer for Simple Job Board, WP Jobster, or other plugins. The only non-WPJM path is the CSV importer, which is part of Pro's Migration module (Career Board → Migration, Pro).

For any non-WPJM source:

  1. Export old data to CSV - most plugins have an export tool; if not, query the database directly:
    SELECT post_title, post_content, post_date, post_status
    FROM wp_posts WHERE post_type = 'your_old_cpt';
    
  2. Use Pro's CSV importer in WP Admin → Career Board → Migration (requires Pro).
  3. Map CSV columns to Career Board fields.
  4. Run import. Career Board creates one wcb_job per CSV row.

These migrations are more art than science - budget extra time and test thoroughly.

Preserving URLs (redirects)

Most plugins use different URL patterns. To avoid breaking SEO:

Career Board serves single jobs at /jobs/{slug}/.

Old plugin Old URL pattern Career Board pattern Redirect needed?
WP Job Manager /job/{slug}/ /jobs/{slug}/ Yes
Simple Job Board /jobpost/{slug}/ /jobs/{slug}/ Yes
WP Jobster /jobs/{slug}/ /jobs/{slug}/ Depends on slug overlap
Custom CPT varies /jobs/{slug}/ Yes

Setting up redirects

Option A - Redirection plugin (recommended)

  1. Install Redirection.
  2. Add a regex rule:
    • Source: /jobpost/(.*)$
    • Target: /jobs/$1
    • 301 permanent.
  3. Verify with a sample URL in Redirection's "Check Redirect" tool.

Option B - .htaccess (Apache)

RewriteRule ^jobpost/(.*)$ /jobs/$1 [R=301,L]

Career Board does not ship a built-in redirect-map UI, so use one of the two options above (a redirects plugin or .htaccess).

Testing the migration

A solid test path before going live:

  1. Staging copy first. Run the migration on a staging copy, not live, the first time. Spend a day kicking the tires.
  2. Sample 20 random old listings. Verify each one rendered correctly on Career Board. Check:
    • Title, description (formatting preserved).
    • Featured image (if any) carried over.
    • Application form works.
    • Old URL redirects to new URL.
  3. Test the apply flow as a fresh candidate. The most common regression: the old plugin used a different field schema, and the application form expects fields the import didn't set.
  4. Run a few search queries that worked on the old board. The results should be similar (Career Board's search is different - not pixel-identical results, but the relevant jobs surface).
  5. Run an SEO crawl. A simple ScreamingFrog scan against the new site catches broken redirects, missing meta, lost canonicals.
  6. Email your top 20 employers and top 100 candidates a week before the cutover, telling them what's changing and what to expect (their login still works, their data is preserved, the URL of their saved searches may change).

After migration

Once live:

  • Monitor the error log for the first 48 hours. Edge cases surface as PHP notices or warnings - check wp-content/debug.log for anything Career Board-related.
  • Watch for support tickets about login issues. The user account table is unchanged, but roles / capabilities may have shifted. Career Board ships its own roles (Employer, Candidate, Job Moderator) backed by wcb_* capabilities; assign the Employer role to migrated posters if their old role doesn't carry the Career Board capabilities.
  • Update the FAQ / help docs on your site - old links, old screenshots, old terminology.
  • Set a 30-day reminder to deactivate redirects you no longer need (after most traffic has stopped hitting old URLs).

What you'll likely have to rebuild

Some things don't migrate cleanly because the underlying models differ:

  • Email templates - Career Board ships its own; old plugin's custom subject lines / branding need to be re-created.
  • Application form field order - Career Board's order is consistent (name, email, resume, cover, custom fields); if your old plugin had a custom layout, re-create with the Field Builder.
  • Theme template overrides - old plugin's templates won't apply to Career Board's blocks. If you had heavy theme customisation, you may need to redo it with Career Board's filter hooks instead.
  • Integration with third-party tools - Zapier connections, ATS integrations, etc. The Career Board REST API is well-documented; you'll rebuild the integrations against the new endpoints.

Where to go next

  • 01-first-day-as-site-owner.md - set up Career Board correctly before importing.
  • The built-in WP Job Manager importer lives on Career Board → Import (Free).
  • Pro's Migration module (with the CSV importer) is documented in the Pro docs - use it for non-WPJM sources.

Multi-Language Job Board

How to run a job board that serves multiple languages, using either WPML or Polylang. Covers translation strategy, how jobs and applications behave across languages, and the gotchas to plan around.

If you only serve one language, skip this - but the same principles apply if you ever decide to expand.

Two valid strategies

Strategy 1: Mirror jobs across languages

Each job exists once per language. A "Senior Engineer" post in English has a French counterpart "Ingénieur Senior" - same role, different translation.

  • Best for: boards where the same employer hires across multiple language markets, and you want each language community to feel native.
  • Cost: the employer (or you) maintain both copies. Mismatched copies - common because translations drift - confuse candidates.

Strategy 2: Bilingual single listings

Each job exists once, in the employer's language. Candidates browse in their chosen language but see the original-language listing if no translation exists.

  • Best for: boards where roles are often remote / international and employers post in whatever language they're most comfortable with.
  • Cost: less duplication, but candidates need to be comfortable reading at least the employer's language for some listings.

Most real boards use Strategy 2 because Strategy 1 demands ongoing translation labour. Strategy 1 makes sense only when you have in-house translators or the employers translate before posting.

What translates and what doesn't

Either strategy, these elements work differently:

Element What gets translated
Job title + description Strategy 1: per copy. Strategy 2: one copy in source language.
Categories / taxonomy Always translated. "Engineering" / "Ingénierie" share the same term ID.
Locations Usually not translated (city names - "Paris" stays "Paris").
Company profiles Per profile; if a company hires in multiple languages, they translate the profile once.
Candidate profiles Per candidate; the candidate writes their bio in their language of choice.
Email notifications Per language; the candidate / employer's user preference determines which template is sent.
UI strings (block labels, buttons) Career Board wraps strings in WPML / Polylang-compatible __() calls and ships a POT template (languages/wp-career-board.pot); generate your own PO/MO, or translate inline in WPML / Polylang String Translation. Since 1.6.0, the plugin is fully translation-ready and bundles ready-made German, French, Spanish, Dutch, and Korean translations - your site loads the matching one automatically if the site language is set to one of those five.
Application form custom fields Per language (Pro: Field Builder).

Setup with WPML

Prerequisites

  • WPML Multilingual CMS + WPML String Translation add-on installed.
  • Languages configured in WPML.
  • WP Career Board Free or Pro.

Career Board ships a wpml-config.xml manifest that WPML and Polylang both read, so the CPTs, taxonomies, and meta keys below are already declared with sensible defaults. The steps here mostly confirm those defaults.

Step 1 - Enable Career Board CPTs in WPML

Career Board's CPTs are wcb_job, wcb_company, wcb_resume, wcb_application, and the admin-only wcb_board. There is no wcb_candidate CPT - candidates are WordPress users and their resumes are the wcb_resume CPT (Pro).

  1. WPML → Settings → Post Types Translation.
  2. The shipped manifest already sets:
    • wcb_job - Translatable.
    • wcb_company - Translatable.
    • wcb_resume - Translatable (usually left as-is; candidates write in their own language).
    • wcb_application - Not translatable (applications shouldn't be duplicated).
    • wcb_board - Not translatable.
  3. WPML → Settings → Taxonomies Translation: the manifest enables translation for wcb_category, wcb_job_type, wcb_tag, wcb_location, and wcb_experience.

Step 2 - Configure custom field translation

Career Board stores job details in post meta. For each meta key WPML should sync or translate:

  1. WPML → Settings → Custom Field Translation.
  2. The shipped manifest already declares these (you rarely change them):
    • _wcb_salary_min, _wcb_salary_max, _wcb_salary_currency, _wcb_salary_type - Copy (numbers/codes are the same across languages).
    • _wcb_apply_url, _wcb_apply_email - Copy.
    • _wcb_deadline - Copy.
    • _wcb_remote, _wcb_featured, _wcb_company_id, _wcb_board_id - Copy.
    • _wcb_company_name, _wcb_tagline - Translate (these are the two public strings that are language-specific).

If you've added custom fields via Pro's Field Builder, decide case-by-case based on whether the data is language-specific.

Step 3 - Translate UI strings

  1. WPML → String Translation.
  2. Filter by domain wp-career-board (Free) and wp-career-board-pro (Pro).
  3. Career Board ships a translation template (languages/ wp-career-board.pot) but no pre-translated PO/MO files. Generate your own translations from the POT (or translate inline in WPML), then save.
  4. For untranslated strings, edit inline in WPML and save.

Step 4 - Run a sample translation

  1. Create a job in your default language.
  2. In the post editor, find the WPML language switcher and create the translation copy. Translate the title and description.
  3. Save the translation.
  4. Test on the frontend: switch language at the top of the site → confirm the translated listing renders.
  5. Test the apply flow in the secondary language - confirm form labels are translated, the email template the candidate gets is in their language.

Setup with Polylang

Prerequisites

  • Polylang (free or Pro).
  • Languages configured under Languages → Languages.

Step 1 - Enable CPTs for translation

  1. Languages → Settings → Custom post types and Taxonomies.
  2. Check (Polylang reads the same wpml-config.xml, so these match the shipped defaults):
    • wcb_job, wcb_company, wcb_resume. Leave wcb_application and wcb_board unchecked.
    • wcb_category, wcb_job_type, wcb_tag, wcb_location, wcb_experience.
  3. Save.

Step 2 - Set fallback behavior

Polylang's defaults are reasonable. Set:

  • Languages → Settings → URL modifications: subdomain, subdirectory, or query parameter. Subdirectories (/fr/) are most SEO-friendly.
  • Hide URL language information for default language - recommended unless you want /en/ prefixed for English content.

Step 3 - Translate UI strings

  1. Languages → Strings translations.
  2. Filter by group "wp-career-board" / "wp-career-board-pro."
  3. Translate each string inline.

Step 4 - Sample translation

Similar to WPML - create a translation post for a job, verify the frontend renders correctly with language switching.

Multi-language with AI features (Pro)

If you have Pro AI enabled and run a multi-language board, a few things to know:

  • Embeddings work cross-language up to a point. OpenAI's text-embedding-3-small model is multilingual - a query in French can match a job description in English with degraded but usable results. For truly cross-language search, you may want to test the embedding behavior with your specific language pair.
  • AI Chat Search shows results in the queried language's listings by default. If a candidate queries in French, only the French-side listings (Strategy 1) or the source-language listings translated to French in display (Strategy 2) are returned.
  • AI Description Writer respects the input language. If you write bullets in French, the description is in French. The AI doesn't auto-translate.
  • AI Application Ranking sends the description + candidate profile in their native languages; the model handles multilingual scoring reasonably for major language pairs but degrades for low-resource languages.

Common multi-language gotchas

Different application form submissions per language

The application form on a French job submits to the same REST endpoint as the English version, and the candidate's user account is the same. Career Board doesn't store a per-application language flag, so if you need language-specific reporting, derive it from the job's language (via WPML / Polylang) or store your own meta key on the wcb_application_submitted action.

Email templates per language

Career Board sends emails in the recipient's language. If the candidate registered with French as their UI language, they receive French notifications regardless of which language the job was posted in.

To verify: in Settings → Emails, each template's strings should be translatable via WPML / Polylang String Translation. If a translation is missing, the default-language template is used as fallback.

Search engine considerations

  • Use hreflang tags so Google knows which listing serves which language. WPML / Polylang adds these automatically when configured.
  • Avoid translating the same job into too many languages if quality suffers - Google penalises auto-translated thin content.

Pro Boards (Multi-Board) and languages

If you use Pro's Multi-Board feature, each board is a separate container. You can:

  • One board per language - "English Jobs" and "French Jobs" as separate boards.
  • One board, multi-language listings within - single board, jobs per language inside.

Most teams pick "one board, multi-language listings" for simplicity. "One board per language" only makes sense if the boards serve genuinely different markets / employers / pricing.

Currency and salary

Salary is stored as a number + currency code. WPML / Polylang doesn't auto-convert. Your options:

  • Show source-currency. Display "$80k-$100k USD" regardless of UI language. Simplest, but UX-suboptimal for non-USD candidates.
  • Convert at display time. Filter the rendered salary output in your theme/child plugin and convert to the candidate's preferred currency using a third-party rate API. More work, better UX. (The salary value and currency are stored in the _wcb_salary_min / _wcb_salary_max / _wcb_salary_currency meta keys.)

Slugs and URLs

When a job is translated, each translation has its own slug:

  • English: /job/senior-engineer/
  • French: /fr/emploi/ingenieur-senior/

If you want each translation's slug to match a hand-picked pattern (e.g. /fr/job/... instead of /fr/emploi/...), configure that in WPML's Permalinks settings.

Testing checklist for multi-language

Before going live:

  • Switch UI language in the header - does the job list reload with translated content?
  • Search a query in language A - do results appear?
  • Apply to a translated job - does the form show in the translated language? Does the candidate get the email in their UI language?
  • Apply to an un-translated job (Strategy 2 only) - does it work gracefully? The candidate should see the source-language listing but with translated UI chrome.
  • Employer dashboard - does it render in the employer's UI language?
  • Hreflang tags present on listing pages - view source, confirm.

Where to go next

Privacy & GDPR Compliance

A complete walkthrough of what data WP Career Board stores, how to make it GDPR / CCPA / similar-regulation compliant, and the day-to-day operations a board owner needs to handle (consent, exports, deletion requests, retention).

This is not legal advice - but it covers the technical operations that translate "be compliant" into "do this in the dashboard."

What data Career Board stores about candidates

A summary so you know what's actually on the line:

Data Where When deleted
User account wp_users table On admin-processed erasure, or admin removal
Candidate profile (email, phone, location, bio) WordPress user + user meta With the user account
Resumes (Pro, uploaded files) wcb_resume CPT + media On erasure (deleted)
Applications submitted wp_posts (CPT wcb_application) On erasure: the candidate's applications are deleted
Cover letters and answers Application meta Deleted with the application
Saved jobs (bookmarks) User meta With the user account
Job alerts (Pro) wcb_job_alerts table (Pro) With the user account
AI vectors (Pro, jobs only) wcb_ai_vectors table (Pro) Kept until the job is deleted

Career Board does not anonymise applications - the privacy eraser deletes the candidate's applications and resumes outright. There is no "Anonymous candidate" preservation and no wcb_anonymize_or_delete filter.

What data Career Board stores about employers

Data Where When deleted
User account wp_users On removal
Company profile (name, logo, about, locations) wcb_company CPT + meta With company removal
Jobs posted wcb_job CPT When the employer deletes them; when a job is permanently deleted, its applications transition to the job_removed status
Credit ledger (Pro) wcb_credit_ledger table (Pro) Never auto-deleted (append-only financial record; admin purges manually if required)
Payment records WooCommerce / PMPro / etc. (Pro checkout) Per that plugin's deletion policy

What you legally need to do (typical GDPR baseline)

  1. Disclose what you collect in a privacy policy on the site.
  2. Obtain consent before collecting (typically a checkbox on registration / apply forms).
  3. Provide data exports when a user requests their data (right of access).
  4. Provide data deletion when a user requests it (right to erasure).
  5. Set a retention policy (don't keep data forever without reason).
  6. Notify on breach within 72 hours of detection.

The technical operations:

Step 1 - Privacy policy text

Career Board doesn't generate your privacy policy text, but here's a template paragraph to add to yours:

Job Board Data: When you register on this site as a candidate or employer, we collect the information you provide (name, email, resume, profile details, job postings, applications). We store this on our servers running WP Career Board. We use this data to show your profile / jobs / applications to relevant parties on the board. We do not sell this data. You can request a full export or deletion of your data at any time from Candidate Dashboard → Settings (Export my data / Delete my account). Requests are processed by the site administrator through WordPress's privacy tools.

AI Features: If we have AI features enabled, your data may be sent to a third-party AI provider (OpenAI, Anthropic Claude, or Ollama on our own server) for processing. See the AI provider's own privacy policy for their handling. You can opt out of AI processing by [linking to the opt-out mechanism if you have one].

Payment Data: If you purchase services (e.g. job posting credits, subscriptions), payment is processed by [WooCommerce / PMPro / etc.] - see their privacy policy for payment data handling.

Update the bracketed bits to your specifics. Always have a lawyer review the final version.

Career Board does not ship a built-in consent checkbox or a "Settings → Privacy → Consent text" screen, and it does not log a _wcb_privacy_consent meta value. If your jurisdiction requires explicit consent at registration or apply time, add it yourself:

  • Use a consent-management / forms plugin, or
  • Add a required checkbox to the registration / apply forms via the form field filters (for example wcb_candidate_form_fields, wcb_application_form_fields_groups) and store the result on the user or application.

Always link your privacy policy from wherever you collect data.

Step 3 - Handling data export requests (Right of Access)

Career Board uses WordPress's standard privacy request flow for both export and erasure - it does not generate its own instant ZIP download.

Option A - User requests it from the dashboard

  1. Candidate Dashboard → Settings → Export my data → Request data export.
  2. This calls WordPress's wp_create_user_request() with the export_personal_data type, sends a confirmation email to the candidate, and enters the request into WordPress's privacy queue.
  3. The candidate clicks the confirmation link; the site administrator then completes the export from WP Admin.

Option B - Admin handles it directly

  1. WP Admin → Tools → Export Personal Data (WordPress's built-in privacy tool).
  2. Enter the user's email and create the request.
  3. Career Board registers a privacy exporter (via wp_privacy_personal_data_exporters), so the candidate's applications and status are included in the WordPress export.
  4. The export is delivered through WordPress's standard download/email mechanism.

Career Board's exporter is paginated, so it works on large accounts without a single timeout-prone query.

Step 4 - Handling data deletion requests (Right to Erasure)

For candidates:

Option A - User requests it from the dashboard

  1. Candidate Dashboard → Settings → Delete my account → Send confirmation email.
  2. This calls WordPress's wp_create_user_request() with the remove_personal_data type and emails a confirmation link.
  3. The candidate clicks the link; the request enters WordPress's privacy queue for the site administrator to complete.

Option A2 - Self-service deletion from the mobile app (1.7.0)

If the site runs the WP Career Board companion mobile app, a member can delete their own account from inside the app without waiting on the administrator: confirm their password and type DELETE to confirm, and the account is suspended immediately and scheduled for deletion after a grace period (14 days by default, filterable with wcb_account_deletion_grace_days). Signing back in during the grace period cancels the deletion. Once the grace period passes, a daily cron job runs wp_delete_user() on the account - the same core WordPress deletion cascade Option B below relies on, so it removes the account the same way an admin-processed erasure would.

Option B - Admin handles it directly

  1. WP Admin → Tools → Erase Personal Data (WordPress built-in).
  2. Enter the user's email and confirm.
  3. Career Board registers a privacy eraser (via wp_privacy_personal_data_erasers) that runs in pages and deletes the candidate's applications (and their attached resumes).

What happens on erasure:

  • The candidate's applications are deleted (wp_delete_post), not anonymised. There is no "Anonymous candidate" placeholder and no wcb_anonymize_or_delete filter - deletion is the only behavior.
  • Removing the user account itself (and reassigning or deleting their authored content) is handled by WordPress's standard user-deletion flow, which the admin runs alongside the erasure.

For employers:

  1. Use WP Admin → Tools → Erase Personal Data (or delete the user in WP Admin → Users). There is no employer-dashboard "Delete Account" button.
  2. When an employer's jobs are permanently deleted, every linked application transitions to the job_removed status (the candidate keeps the row in their history).
  3. Credit ledger (Pro): not deleted (append-only financial record). If a jurisdiction requires it, the admin must purge the ledger table manually.

Step 5 - Retention policy

Career Board does not ship a retention settings screen or a retention cron - there is no "Settings → Privacy → Retention" page and no wcb_privacy_retention_cron. The daily crons that do exist handle job expiry, featured-listing expiry, and deadline reminders, not data retention.

If you need scheduled PII purges (e.g. delete applications older than N months), implement them yourself - schedule a WP-Cron event that runs your own cleanup against the wcb_application posts, and document the policy in your privacy notice.

Career Board does not set its own tracking cookies. Saved jobs (bookmarks) are stored as _wcb_bookmark user meta for logged-in users - there is no wcb_saved_jobs cookie and no logged-out bookmark feature in Free.

The only cookies in play are WordPress's standard authentication cookies, the same as any WordPress site. Cover those in your cookie banner as you would for any WordPress install.

Step 7 - AI features and data exposure (Pro)

If you have Pro AI enabled, additional disclosure is needed:

  1. Update privacy policy with a section like:

    "We use AI to power [list of features]. When you submit data (resume, profile, application), it may be sent to our AI provider ([OpenAI / Anthropic Claude / Ollama]). Their data handling is governed by [provider URL]."

  2. Per-feature opt-out (optional, custom). Add a checkbox on the apply form via the wcb_application_form_fields_groups filter, then act on it from the wcb_application_submitted action to skip AI ranking when it is unchecked.

  3. Use Ollama for sensitive data. If you can't share resume / application content with a US LLM (HIPAA, sensitive sectors), run Ollama on your server. See ../ai-features/02-setup-and-providers.md.

Step 8 - Data Processing Agreement (DPA)

For GDPR compliance, your DPA needs to cover:

  • Your role: controller (you decide what's collected).
  • Sub-processors:
    • WordPress hosting provider (e.g. SiteGround, Kinsta).
    • Payment processor (WooCommerce + Stripe / PayPal).
    • AI provider (if Pro AI is on).
    • Email service (if using SMTP plugin's provider).
  • Each sub-processor needs its own DPA, which you reference in yours.

This is paperwork, not technical setup. The plugin's role is to make sure the data flow doesn't include unexpected processors.

Step 9 - Breach response checklist

If you suspect a breach (unauthorised access, data leak):

  1. Identify scope. Which tables / files / accounts were exposed?
  2. Contain. Force-rotate all admin / employer passwords. Disable the affected user accounts if compromised.
  3. Notify affected users within 72 hours (GDPR requirement). Pull the affected user list from WP Admin → Users (filter by the Career Board roles) or with WP-CLI (wp user list).
  4. Notify authorities if the breach meets the threshold for your jurisdiction (each EU state's DPA, ICO in the UK, etc.).
  5. Patch. Fix the underlying cause. Common causes: outdated plugin, weak admin password, compromised host.
  6. Document. Keep records of what happened, what you did, what was disclosed - for regulator audits.

Common compliance mistakes

  • No consent checkbox at registration. Career Board does not ship one - add your own (consent plugin or a required field via the form filters) if your jurisdiction requires it.
  • Publishing job activity to the BP stream. Free posts a "[Member] posted a new job" activity entry on publish, and Pro can broadcast more events. Make sure your privacy notice covers any activity that reveals hiring/job-search behaviour.
  • AI providers not disclosed. Adding Pro AI without updating the privacy policy is a quick way to be non-compliant. Always update the policy AND notify existing users of the change.
  • Manual database deletes. Don't delete rows by hand - use WP's privacy eraser (Tools → Erase Personal Data) so Career Board's eraser removes the candidate's applications and resumes consistently.

Where to go next

Developer Guide

Hooks reference, REST API, WP-CLI commands, and extension cookbook.

Developer Guide - Overview

WP Career Board is built to be extended. The plugin fires 134 unique hooks (actions and filters), registers 46 REST routes, 5 WP-CLI command groups, and ships a JSON manifest that lets your code (or another plugin) reach into every part of the job-board flow without forking the source.

Version note: this guide tracks WP Career Board 1.7.0. Exact counts are re-enumerated on every release in audit/manifest.summary.json - treat that file as the canonical number if it ever disagrees with this prose.

Use this guide when:

  • You're building a custom job-board theme or feature.
  • You're writing a companion plugin that integrates with Career Board (e.g. a Slack notifier, a Salesforce sync, a custom apply flow).
  • You're auditing the plugin's surface area before going live.

For customers running a job board: use the for-employers, for-candidates, and admin-guide directories instead. This section assumes you read code.

Architecture at a glance

Layer Where Purpose
Blocks blocks/<name>/render.php + view.js Customer-facing UI - server-rendered, hydrated by the Interactivity API
Shortcodes core/class-plugin.php::register_shortcodes() 18 shortcode tags wrapping the frontend blocks (page builders, classic editor)
REST API api/endpoints/class-*-endpoint.php 41 routes under wcb/v1/* - all extending WCB\Api\RestController
Modules modules/<area>/ Feature modules: jobs, applications, candidates, employers, boards, antispam, gdpr, moderation, notifications, themeintegration
Core services core/class-*.php Cross-cutting: Settings, Abilities, Locations, Pro coordination, Theme accent bridge
CLI cli/class-*.php wp wcb * command groups - jobs, applications, migrate, scale benchmark

Every layer follows the same conventions:

  • All globals prefixed wcb_.
  • All abilities use wcb/<slug> (kebab-case, namespaced).
  • All REST routes register through WCB\Api\RestController.
  • All DB writes go through $wpdb->prepare().

Contents

Doc What's inside
02-hooks-reference.md Every action and filter the plugin fires, grouped by area
03-rest-api.md The full REST endpoint catalog with auth, params, response shape
04-wp-cli.md WP-CLI commands and arguments
05-extension-cookbook.md Recipes for common extension tasks

Companion plugin development

If you're building a Pro-like companion plugin, also read:

  • wp-career-board-pro/docs/website/developer-guide/02-extending-free.md
    • the canonical contract for extending Free, including the dependency guard, REST namespace sharing, and lockstep version requirements.
  • plan/INVARIANTS.yaml in either repo - machine-enforceable architectural invariants the local-CI gate checks on every commit.

Where the source of truth lives

For introspecting the plugin programmatically:

  • audit/manifest.json - canonical inventory of every block, REST endpoint, hook, CPT, taxonomy, capability, service, and CLI command. Generated by /wp-plugin-onboard. Refreshed on every release.
  • audit/journeys/ - customer-flow regression sentinels. Each journey is a Markdown file that the smoke skill walks before a release tag.
  • audit/qa-coverage.json - coverage gate tracking which REST/CLI/hook surfaces have regression tests. Pre-commit hook blocks reductions in coverage.

If you're building tooling that reads any of these, do so via the manifest's $schema - it's stable and versioned.

Hooks Reference - Actions and Filters

WP Career Board fires 134 unique wcb_-prefixed hooks (49 actions and 85 filters, Free only - Pro adds its own; see the Pro developer guide), ground-truth verified by grepping every do_action()/apply_filters() call site in the plugin source. The most useful integration hooks are grouped by area below; the full file:line inventory is in audit/manifest.json#/hooks_fired (that inventory is a representative sample, not exhaustive - it currently lists fewer entries than actually exist in code; verify by grep when a hook isn't listed there).

How to use this list: every hook is fired with do_action() or apply_filters() somewhere in the plugin source. The full file:line is in audit/manifest.json#/hooks_fired. The arg signature for any hook can be found by grep against the hook name in the codebase.

Lifecycle / job posting

Hook Type Fires when
wcb_pre_job_submit Filter Before a job is created. Return WP_Error to abort.
wcb_before_create_job Filter Modify the wp_insert_post arg array before creation.
wcb_job_created Action After a job is inserted. Args: $job_id, $request.
wcb_before_update_job Filter Modify the update arg array before save.
wcb_job_updated Action After a job update completes. Args: $job_id, $request.
wcb_before_delete_job Filter Return false to abort the delete.
wcb_job_deleted Action After job is removed. Args: $job_id.
wcb_job_republished Action When a job is republished after expiry. Args: $job_id.
wcb_job_approved Action When admin approves a pending job. Args: $job_id.
wcb_job_rejected Action When admin rejects a job. Args: $job_id, $reason.
wcb_job_expired Action When a job's expiry date passes during the daily sweep. Args: $job_id.
wcb_check_job_expiry Action Cron schedule hook - the daily WP-Cron event that runs the job-expiry sweep.
wcb_deadline_reminder Action Fires once per candidate while sending a deadline reminder. Args: $user_id, $job_id, $days_left. (The cron schedule hook that drives this is wcb_send_deadline_reminders.)
wcb_featured_expired Action When a featured job's promotion window ends. Args: $job_id. (Driven by the wcb_expire_featured_jobs daily cron event.)

Moderation / Report a Job

The Report-a-Job flow (any logged-in user can flag a listing; a moderator dismisses or unpublishes it) fires these:

Hook Type Fires when
wcb_job_reported Action A logged-in user reports a job (deduped per user). Args: $job_id, $reason, $user_id.
wcb_job_flag_resolved Action A moderator resolves a job's flags (dismiss or unpublish). Args: $job_id, $action.
wcb_moderate_jobs_ability_check Filter Return a bool to override the moderation permission check.

Moderation / Member safety (1.7.0)

The member report/block surface backing MembersEndpoint (POST /users/{id}/report, POST/DELETE /users/{id}/block) and the admin Candidates screen's suspend bulk action - see 03-rest-api.md.

Hook Type Fires when
wcb_member_reported Action A member reports another member (deduped per reporter). Args: $target_user_id, $reason, $reporter_user_id.
wcb_member_blocked Action A member blocks another member. Args: $blocker_user_id, $blocked_user_id.
wcb_member_unblocked Action A member unblocks another member. Args: $blocker_user_id, $unblocked_user_id.
wcb_member_suspended Action An admin suspends a member from the Candidates admin screen bulk action. Args: $user_id.
wcb_member_unsuspended Action An admin lifts a member suspension. Args: $user_id.

Account deletion (1.7.0)

Self-service account deletion (AccountDeletionEndpoint / AccountDeletionService) - see 03-rest-api.md.

Hook Type Fires when
wcb_account_deletion_requested Action A member schedules deletion of their own account (grace period > 0). Args: $user_id, $scheduled_timestamp.
wcb_account_deletion_cancelled Action A member cancels a pending deletion. Args: $user_id.
wcb_account_deletion_executing Action Immediately before a due deletion calls wp_delete_user() (daily wcb_process_account_deletions cron, or immediately if the grace period is 0). Args: $user_id.
wcb_account_deletion_grace_days Filter Override the grace period in days before a requested deletion is finalized. Default 14; 0 deletes immediately.
wcb_account_deletion_password_required Filter Return false to skip the password re-check (e.g. for SSO/passwordless accounts). Args: $required, $user_id. Default true.

Lifecycle / applications

Hook Type Fires when
wcb_pre_application_submit Filter Before an application is created. Return WP_Error to abort (custom anti-spam, eligibility checks, etc.).
wcb_before_create_application Filter Modify wp_insert_post arg array.
wcb_application_submitted Action After successful submit. Args: $app_id, $job_id, $candidate_id.
wcb_application_status_changed Action When status moves (submitted -> reviewing -> shortlisted -> rejected/hired/withdrawn/job_removed). Args: $app_id, $old_status, $new_status.
wcb_application_withdrawn Action Candidate withdrew. Args: $app_id, $job_id, $candidate_id.
wcb_application_deleted Action Application post deleted. Args: $app_id, $job_id.
wcb_application_form_fields Action Inside the apply form template - render extra <input>s here.
wcb_application_form_fields_groups Filter Add a group of custom fields to the apply form.
wcb_guest_applications_claimed Action After a newly-registered user's prior guest applications (matched by email, post_author=0 + _wcb_guest_email) are reassigned to their new account. Args: $user_id, $claimed_application_ids.

Lifecycle / candidates and employers

Hook Type Fires when
wcb_candidate_registered Action After a candidate signup completes. Args: $user_id, $request.
wcb_employer_registered Action After an employer signup completes. Args: $user_id, $request.
wcb_employer_banned Action After an admin bans an employer from the admin Employers screen. Args: $user_id.
wcb_employer_unbanned Action After an admin lifts an employer ban. Args: $user_id.
wcb_candidate_form_fields Filter Add fields to the candidate registration form.
wcb_company_form_fields Filter Add fields to the company-profile edit form.

Credits and pricing

Hook Type Fires when
wcb_credits_enabled Filter Return true if Pro credits are active.
wcb_employer_credit_balance Filter Return the current user's credit balance (Pro routes to SDK).
wcb_credit_purchase_url Filter URL the "Buy Credits" button points at.
wcb_credit_low_threshold Filter Balance below this triggers the low-credits banner.
wcb_board_credit_cost Filter Credits required to post to a board. Args: $cost, $board_id.
wcb_job_republish_credit_cost Filter Cost to republish an expired job.

All credit filters above are fired by Free (so blocks and the employer dashboard have a consistent surface) but only return meaningful values when Pro is active. In Free they default to "credits disabled" / empty URL / zero balance.

REST response shaping

The wcb_rest_prepare_* family is your hook into every REST response. Each fires after the controller builds the row and before it's returned - modify, redact, or augment.

Hook Adjusts the response for Filter args
wcb_rest_prepare_job Single job + collection items $data, $post, null
wcb_rest_prepare_application Single application + lists $data, $post, $request, $viewer_role
wcb_rest_prepare_candidate Candidate profile $data, $user, null
wcb_rest_prepare_company Company profile $data, $post, null
wcb_job_response Legacy alias fired alongside wcb_rest_prepare_job for back-compat $data, $post

Notes:

  • For wcb_rest_prepare_candidate the second argument is a WP_User, not a WP_Post.
  • The third argument is a WP_REST_Request placeholder and is null on the job/candidate/company filters - do not depend on it there.
  • wcb_rest_prepare_application's fourth argument is the viewer role string (candidate or employer), letting you redact fields per audience. There is no generic single/collection/ embed context argument.

Pro adds: wcb_rest_prepare_board, wcb_rest_prepare_board_stage, wcb_rest_prepare_notification, wcb_rest_prepare_resume.

Block + shortcode extension

Hook Type Use it to
wcb_module_renders Filter Pass an array of dashboard module IDs to control which modules the employer/candidate dashboards render.
wcb_job_form_fields Filter Add field groups to the job form.
wcb_job_form_step1_fields Action Inject extra fields into the 4-step wizard's step 1. Args: $attributes. Companion actions: wcb_job_form_step2_fields, wcb_job_form_step3_fields, and wcb_job_form_step4_preview.
wcb_job_form_simple_extra_fields Action Inject extra fields into the single-page job form. Args: $attributes.
wcb_application_form_fields Action Inject extra fields into the apply panel. Args: $job_id.
wcb_application_form_fields_groups Filter Register grouped custom apply-form fields that the apply endpoint will persist as _wcb_application_field_<key>. Args: $groups, $job_id.
wcb_job_listing_data Filter Per-card data in the listings block. Args: $card, $post.
wcb_job_listings_board_options Filter The boards shown in the listings UI's board picker.
wcb_job_listings_query_args Filter Modify the WP_Query args for the listings server-side query.
wcb_job_listings_api_base Filter Override the REST base the listings block fetches from.
wcb_default_filter_order Filter Reorder or add to the listings block's filter groups. Default ['type', 'experience', 'category', 'tags', 'location', 'board', 'salary']; a saved-per-block filterOrder attribute is then intersected against this list, so a group not present here can never be shown. Since 1.6.0.
wcb_job_listings_filters_top Action Inside the listings block template, immediately above the filter bar. No args.
wcb_job_listings_filters_bottom Action Inside the listings block template, immediately below the filter bar. No args.
wcb_before_card_footer Action Inside each job card, before the footer row. Args: $job_card, $job_post.
wcb_after_card_footer Action Inside each job card, after the footer row. Args: $job_card, $job_post.
wcb_job_form_initial_state Filter Add keys to the 4-step job form's Interactivity API initial state. Extend view.js to read the new key. Args: $state, $attributes.
wcb_job_form_simple_initial_state Filter Same, for the single-page job form. Args: $state, $attributes.
wcb_candidate_resumes_state Filter Inject maxResumes/resumeCount (or other resume-cap fields) into the candidate dashboard's Interactivity state. Pro uses this for resume-archive cap enforcement. Args: $state, $candidate_user_id.
wcb_company_sidebar_before Action Company-profile block, before the sidebar renders. Args: $company_id.
wcb_company_sidebar_after Action Company-profile block, after the sidebar renders. Args: $company_id.
wcb_company_sidebar_blocks Filter Add or remove sidebar block IDs shown on the company-profile page. Args: $blocks, $company_id.
wcb_save_custom_field Filter Sanitize a custom profile/form field before it is persisted. Args: $value, $key, $owner_id.
wcb_shortcode_attr_aliases Filter Add to the camelCase to lowercase attribute map (so [wcb_job_listings boardId="1"] works).
wcb_search_active_shortcodes Filter Tag/prefix names for the body-class detector. Extend if you register custom shortcodes that should also force the wcb-page body class.
wcb_page_needs_frontend_assets Filter Force-load (or skip) the Career Board frontend bundle on a given request.
wcb_jobs_collection_params Filter Modify the get_collection_params() schema (query args) accepted by GET /jobs.

Frontend JS events (browser CustomEvent, not PHP hooks)

Two blocks coordinate through document-level CustomEvents so listeners (including Pro's job-map block) can react without a shared Interactivity store:

Event Dispatched by Detail Fires when
wcb:search job-search and job-filters blocks { query, filters } The visitor changes the search query or a filter, after the URL is updated with history.pushState.
wcb:results job-listings block { jobIds: number[], total: number } Since 1.6.0. After a listings fetch resolves, so a listener can sync to the actually-visible job set - wcb:search alone only carries the query/filters, not which jobs matched.
document.addEventListener( 'wcb:results', ( event ) => {
    console.log( 'Visible job IDs:', event.detail.jobIds );
} );

Settings and pages

Hook Type Use it to
wcb_install_default_settings Filter Modify the seed values on plugin install.
wcb_settings_sanitize Filter Sanitize a custom settings key before save.
wcb_settings_tabs Filter Add a tab to the Settings UI.
wcb_settings_tab_<slug> Action Render content for a custom tab (the slug becomes the suffix).
wcb_settings_tab_antispam Action The built-in Anti-Spam tab. Hook to add additional anti-spam controls.
wcb_settings_tab_emails Action The Emails tab - extend with custom email templates.
wcb_page_settings Filter Modify which pages are mapped for "Career Board page" detection.
wcb_app_page_ids Filter Add page IDs that should get the wcb-page body class.
wcb_apply_page_class Filter Opt out a page from the wcb-page body class entirely.
wcb_container_max_width Filter Override the 1200px content-column default.
wcb_registered_emails Filter Add a new transactional email type to the plugin's email registry.
wcb_email_template_dirs Filter Add a directory Career Board searches for {slug}.php email template overrides (theme override still wins first).
wcb_fullwidth_block_names Filter Add a block name (namespace/slug) to the list that triggers the full-width page template + body class. Pro adds its resume-archive/recruiter-search blocks here.
wcb_candidate_requires_role Filter Return true to require the explicit wcb_candidate role/cap before a logged-in user can apply (default follows the candidate_requires_role setting, off).
wcb_bot_ua_pattern Filter Override the PCRE pattern (no delimiters) used to detect bot User-Agents for anti-spam/analytics purposes.
wcb_job_views_retention_days Filter Override how many days of wcb_job_views analytics rows are kept before the daily prune deletes them. Default 90, floored at 30. Since 1.2.9.
wcb_min_app_version Filter Set the minimum mobile-app version the settings/app-config endpoint reports, letting the app force an upgrade. Default "1.0.0". Since 1.7.0.
wcb_app_enabled Filter Return true/false to override whether settings/app-config reports the mobile app as enabled for this site. Default: whether Pro is active. Since 1.7.0.

Setup wizard

Hook Type Use it to
wcb_wizard_steps Filter Add a step to the setup wizard. Each entry: title, template (absolute path), button_text, keyed by a unique slug.
wcb_wizard_required_pages Filter Add a page (title + content) the wizard's "Create Pages" step and Settings "Create Missing Pages" action will create. Keyed by the wcb_settings option key that stores the resulting page ID.
wcb_wizard_completed Action After the wizard's last step.
wcb_wizard_force_render Filter Force the wizard to render even when is_setup_complete() is true.
wcb_wizard_complete_redirect Filter Override the URL the wizard redirects to on finish.
wcb_companions Filter Add an entry (label, description, why) to the companion-plugin catalog shown by the installer and admin screen. Since 1.4.6.

Pro-coordination filters (Free side)

These let Free check whether Pro is active and gate behavior. Pro hooks them to return true / version / license status.

Hook Returns
wcb_pro_active bool - is Pro plugin running?
wcb_pro_licensed bool - is the Pro license valid?
wcb_pro_version string - Pro version, e.g. "1.4.3"
wcb_pro_ai_enabled bool - is the Pro AI bundle enabled?
wcb_pro_upsell_url string - where the "Upgrade to Pro" CTA points
wcb_pro_settings_saved_notice Filter - message for the post-save admin notice

AI feature-availability filters

Free fires these so blocks can render the right call-to-action; Pro returns true when the corresponding AI feature is licensed and enabled. In Free they default to false.

Hook Returns
wcb_ai_description_enabled bool - show the AI job-description helper in the job forms.
wcb_ai_matching_available bool - candidate dashboard shows AI job matching.
wcb_ai_ranking_available bool - employer dashboard shows AI applicant ranking.
wcb_ai_completion_available bool - job-single page offers the AI cover-letter / completion helper.
wcb_pro_alerts_enabled bool - Pro job-alerts feature is active.
wcb_pro_resumes_enabled bool - Pro resume directory is active.

Miscellaneous

Hook Type Use it to
wcb_industries Filter Add or rename industry categories used by the company profile.
wcb_currency_catalog Filter Add a currency to the salary-currency dropdown.
wcb_board_currency Filter Override per-board currency (Pro typically).
wcb_board_options_for_employer Filter Modify the boards dropdown shown to an employer (Pro filters to user-accessible groups).
wcb_job_board_id Filter Resolve which board a job belongs to.
wcb_job_default_status Filter Initial status on submission.
wcb_job_default_expiry_days Filter Default job-expiry window.
wcb_jobs_post_filter Filter After the listings query but before render - add transformations.
wcb_jobs_allowed_meta_filters Filter Allowlist of meta keys the metaFilter block attribute may query (prevents arbitrary-meta probes).
wcb_resume_pdf_attachment_id Filter Resolve the attachment ID used as a candidate's resume PDF.
wcb_theme_accent_primary Filter Primary accent color used by blocks. Args: $accent, $template. Driven by the theme accent bridge (core/class-theme-accent-bridge.php).
wcb_admin_email_log_response Filter Modify the email-log REST response.
wcb_cli_abilities Filter Map WP-CLI runs to ability slugs for permission checks.
wcb_import_extra_cards Action Add cards to the Import admin page.
wcb_rest_app_config Filter Frontend boot config shipped to the Interactivity API and the mobile/companion app - see the app-config route in 03-rest-api.md.
wcb_sample_data_installed Action After the setup wizard seeds sample content.
wcb_sample_data_removed Action After sample content is removed (wizard or uninstall).
wcb_notification_created Action Fires after a notification is created so a centralised notification center (e.g. BuddyNext) can mirror it without re-deriving the message. Free has no in-app bell, so it fires once per real email send (admin test sends are skipped). Single arg: an array { user_id, event_type, message, link, id } - message is the rendered email subject, link is a best-effort deep link, id is 0 on Free. Pro fires the same hook from its notification bell with the inserted row id.

Listening pattern (example)

add_action( 'wcb_job_created', function ( $job_id, $request ) {
    // Notify a Slack channel when a new job lands.
    if ( $request->get_param( 'featured' ) ) {
        my_slack_post( "Featured job posted: " . get_the_title( $job_id ) );
    }
}, 10, 2 );
add_filter( 'wcb_rest_prepare_job', function ( $row, $post ) {
    // Add a `is_remote_friendly` flag based on a meta value.
    $row['is_remote_friendly'] = (bool) get_post_meta( $post->ID, '_remote_friendly', true );
    return $row;
}, 10, 2 );

How to confirm a hook signature

The fastest way to see the actual arg signature:

grep -rn "do_action\\s*(\\s*'wcb_job_created'" wp-content/plugins/wp-career-board/

That returns the file:line of every firer; open it and read the surrounding lines for the parameter shapes.

For the Pro-side hooks, see docs.wbcomdesigns.com/docs/wp-career-board-pro/developer-guide/03-hooks-reference.

REST API Reference

WP Career Board registers 46 REST routes under the wcb/v1 namespace. Every endpoint extends WCB\Api\RestController, which owns the shared response envelope and the abilities-aware permission helper.

Authentication

Most endpoints require a logged-in WordPress user and a valid nonce. Use the standard WP REST nonce in headers:

fetch( '/wp-json/wcb/v1/jobs', {
    headers: { 'X-WP-Nonce': wpApiSettings.nonce },
    credentials: 'same-origin'
})

For server-to-server calls, generate an application password (Users -> Profile -> Application Passwords) and use HTTP Basic auth.

A small set of endpoints permit guest access - the read-only jobs, companies, candidates, employers, and search endpoints, the candidate/employer registration endpoints, and the apply endpoint. Guest applications are always allowed - submit_permissions_check() returns true unconditionally for a logged-out request, no setting gates this; a logged-in user must instead hold the wcb/apply-jobs ability. Guest endpoints use the __return_true permission_callback (except the apply endpoint, which uses the custom check above).

Abuse prevention on submission endpoints comes from the anti-spam module (an always-on honeypot field plus an optional CAPTCHA provider - Google reCAPTCHA v3 or Cloudflare Turnstile), which hooks rest_pre_dispatch and rejects spammy requests before they reach the handler. There is no per-IP request-rate limiter.

Response envelope

Every endpoint returns either a WP_REST_Response (success) or a WP_Error (failure). Success shape varies by endpoint; failure shape is consistent:

{
    "code": "wcb_invalid_status",
    "message": "Invalid status.",
    "data": { "status": 400 }
}

The wcb_* prefix on error codes is the plugin's namespace - addons should mirror this convention with their own prefix.

Routes by area

All routes below are relative to /wp-json/wcb/v1.

Jobs

Method Route Auth Purpose
GET /jobs guest OK List jobs with filters: s, category, location, type, experience, remote, salary_min, salary_max, board_id, per_page, page
GET /jobs/{id} guest OK Single job (full detail)
POST /jobs employer Create a job
PUT /jobs/{id} author or admin Update a job
DELETE /jobs/{id} author or admin Delete a job
POST /jobs/{id}/approve moderator Approve a pending job
POST /jobs/{id}/reject moderator Reject a pending job (requires reason)
POST /jobs/{id}/bookmark logged-in Toggle a saved/bookmarked job
POST /jobs/{id}/report logged-in Report a job for moderation (deduped per user)
POST /jobs/{id}/resolve-flag moderator Dismiss or unpublish a flagged job
GET /jobs/{id}/applications author or admin List applications for a job

Republishing an expired job is available via WP-CLI (wp wcb job ...) and the admin Jobs screen, not as a dedicated REST route.

Since 1.7.0, every job card returned by GET /jobs and GET /jobs/{id} carries viewer-relative fields for a logged-in requester: is_bookmarked, has_applied, application_status, and viewer_can_apply. These are computed per-request (JobsEndpoint::enrich_viewer_state(), batch-fetched - one usermeta read plus one applications query per page, never per-row) rather than baked into the shared query cache, so they stay correct across requesters. A guest or a request with no matching user gets is_bookmarked: false, has_applied: false, application_status: null, viewer_can_apply: false.

Applications

Method Route Auth Purpose
POST /jobs/{id}/apply candidate or guest Submit application (guests always allowed; a logged-in user needs the wcb/apply-jobs ability)
GET /applications/{id} candidate or job-owner Single application detail
DELETE /applications/{id} candidate owner Withdraw application
PUT /applications/{id}/status employer/admin Change status (submitted/reviewing/shortlisted/rejected/hired)
GET /candidates/{id}/applications self or admin Candidate's application history
POST /candidates/resume-upload candidate Upload a resume PDF

Candidates

Method Route Auth Purpose
POST /candidates/register guest Register a new candidate
GET /candidates/{id} guest OK Candidate profile (public read; the callback allows any requester)
PUT /candidates/{id} self or admin Update profile
GET /candidates/{id}/bookmarks self or admin List saved jobs (read-only - toggle via POST /jobs/{id}/bookmark)
GET /candidates/{id}/saved-companies self or admin List saved companies (read-only - toggle via POST /companies/{id}/bookmark)
GET /candidates/{id}/saved-resumes self or admin List saved resumes (read-only)
POST /candidates/me/privacy/{action} self GDPR self-service: export or erase personal data

Account

Method Route Auth Purpose
GET /account logged-in Read the current user's Career Board account profile
PUT /account logged-in Update the current user's account profile

Account deletion

Self-service account deletion for the mobile/companion-app surface (Apple 5.1.1(v)). Added in 1.7.0 - AccountDeletionEndpoint, backed by WCB\Modules\Account\AccountDeletionService. Deletion is scheduled with a grace period (wcb_account_deletion_grace_days filter, default 14 days) rather than run immediately: the account is suspended (reuses the _wcb_employer_banned flag) and its Application Passwords are revoked for the window, then the daily wcb_process_account_deletions cron finalizes anything past its date by calling wp_delete_user() - the existing delete-user cascade runs, nothing is re-implemented. Cancelling is never gated by the suspension the schedule itself applied, so the grace period is not a one-way door.

Method Route Auth Purpose
DELETE /me logged-in Request deletion of the caller's own account (password + confirm: "DELETE"); returns 202 when scheduled, 200 when deleted immediately (0-day grace)
GET /me/deletion logged-in Pending-deletion status (active or scheduled + scheduled_for)
DELETE /me/deletion logged-in Cancel a pending deletion

Administrator accounts (manage_options) cannot be deleted through this route.

Member safety - report and block

Member-to-member report/block surface for user-generated-content app review (Apple 1.2). Added in 1.7.0 - MembersEndpoint. Reports reuse the same per-reporter flag shape the Report-a-Job flow uses, stored as user-meta on the reported member; blocks reuse the non-unique-usermeta list pattern the job-bookmark feature uses.

Method Route Auth Purpose
POST /users/{id}/report logged-in Report a member (reason enum: spam, scam, fake_profile, harassment, offensive; details optional) - deduped per reporter
POST /users/{id}/block logged-in Block a member
DELETE /users/{id}/block logged-in Unblock a member
GET /me/blocked logged-in The caller's blocked-members list (batch-loaded, no N+1)

A member cannot report or block themself (wcb_cannot_report_self / wcb_cannot_block_self, 400). A site owner suspends a member from the admin Candidates screen bulk action, which fires wcb_member_suspended / wcb_member_unsuspended - see the hooks reference.

Employers and companies

Method Route Auth Purpose
POST /employers/register guest Register a new employer
POST /employers admin (wcb/manage-company) Create an employer/company directly (admin tooling, not self-registration)
GET /employers/{id} guest OK Employer detail (public read)
PUT /employers/{id} self or admin Update an employer profile
GET /employers/{id}/jobs guest OK Employer's job postings
GET /employers/{id}/applications self or admin Applications across the employer's jobs
POST /employers/{id}/logo self or admin Upload the company logo
GET /employers/me/jobs employer The current employer's own jobs
GET /companies guest OK List companies with filters (single company is read from this collection)
POST /companies/{id}/bookmark logged-in Toggle a saved company
POST /companies/{id}/trust admin (wcb/manage-settings) Cast a trust signal on a company

There is no GET /employers list route - an employer's profile is the same wcb_company post type companies use, so a public employer directory is served through GET /companies, not a dedicated employers-collection endpoint.

Search and settings

Method Route Auth Purpose
GET /search guest OK Unified search across jobs and companies
GET /settings/app-config guest OK Frontend boot config consumed by the Interactivity blocks and the mobile/companion app

Plugin settings are saved through the admin Settings page (the WordPress Settings API), not a REST write route.

GET /settings/app-config (SettingsEndpoint::get_app_config()) was extended in 1.7.0 with the mobile-app contract: feature_toggles (reporting, blocking, account_deletion, plus the existing guest_apply/bookmarks/Pro-gated flags), a white-label legal object (privacy_policy_url, terms_url, eula_url, community_guidelines_url, abuse_contact_email), branding fields (accent_color, logo_url, login_bg_url, dark_mode_default), min_app_version (filterable via wcb_min_app_version), contract_version, and app_enabled (filterable via wcb_app_enabled, defaults to whether Pro is active). The whole payload passes through wcb_rest_app_config before it's returned - see the hooks reference. Additive-only: existing keys are never renamed or retyped.

Admin

Method Route Auth Purpose
GET /admin/emails/log admin Paginated transactional-email send log
POST /admin/emails/test admin Fire a test send for a named email template
POST /admin/dismiss-banner logged-in Mark an admin banner dismissed for the current user

Import and setup wizard

Method Route Auth Purpose
GET /import/status admin Poll a running import's progress
POST /import/run admin Start or step a content import
POST /wizard/create-pages admin Create the required Career Board pages
POST /wizard/sample-data admin Install demo content
POST /wizard/remove-sample-data admin Remove the demo content
POST /wizard/complete admin Mark the setup wizard finished

Modifying responses

Career Board responses pass through a wcb_rest_prepare_* filter (see 02-hooks-reference.md) before they are returned. Check the filter-argument table in the hooks reference - the signature is not the same for every entity. To add a custom field to the jobs response:

add_filter( 'wcb_rest_prepare_job', function ( $row, $post ) {
    $row['custom_score'] = my_score_function( $post->ID );
    return $row;
}, 10, 2 );

Adding new routes

The cleanest way is to extend WCB\Api\RestController:

namespace MyAddon;

class My_Endpoint extends \WCB\Api\RestController {

    public function register_routes(): void {
        register_rest_route(
            $this->namespace,  // wcb/v1
            '/my-thing/(?P<id>\d+)',
            array(
                'methods'             => \WP_REST_Server::READABLE,
                'callback'            => array( $this, 'get_item' ),
                'permission_callback' => function (): bool {
                    return $this->check_ability( 'wcb/post-jobs' );
                },
                'args'                => array(
                    'id' => array(
                        'validate_callback' => static fn( $v ) => is_numeric( $v ),
                        'sanitize_callback' => 'absint',
                    ),
                ),
            )
        );
    }

    public function get_item( \WP_REST_Request $request ): \WP_REST_Response {
        // ... your handler
    }
}

add_action( 'rest_api_init', static function () {
    ( new My_Endpoint() )->register_routes();
});

You inherit the response envelope, current_user_id(), permission_error() (401 vs 403), and the abilities-aware check_ability( $ability ) helper - pass the ability slug you want to gate on. Route-path disjointness with the plugin's own routes is enforced by the architecture-checks gate (invariant A3 in Pro's INVARIANTS.yaml).

Abuse prevention

There is no per-IP request-rate limiter. Submission endpoints are protected by the anti-spam module instead: an always-on honeypot field plus an optional CAPTCHA provider (Google reCAPTCHA v3 or Cloudflare Turnstile), configured under Settings -> Anti-Spam. The module validates on the rest_pre_dispatch filter and rejects spammy submissions before the route handler runs.

WP-CLI Reference

WP Career Board ships 5 WP-CLI command groups for automation, migration, and scale testing.

wp wcb <command> <subcommand> [options]

wp wcb job

Operate on wcb_job posts.

Subcommand Purpose
wp wcb job list List jobs, with filters such as --status=pending
wp wcb job approve <id> Approve a pending job
wp wcb job reject <id> --reason="..." Reject a job with a reason
wp wcb job expire [<id>] Run the expiry sweep manually (same as the daily cron); pass an ID to expire one job
wp wcb job run-expiry Run the scheduled expiry cron callback directly

Example - bulk reject:

wp post list --post_type=wcb_job --post_status=pending --field=ID \
  | xargs -I{} wp wcb job reject {} --reason="Duplicate posting"

wp wcb application

Operate on applications.

Subcommand Purpose
wp wcb application list List applications (filter with --candidate_id=<id> or --job_id=<id>)
wp wcb application update <id> --to=<status> Update an application's status (fires wcb_application_status_changed)

wp wcb migrate

Import legacy job-board content into Career Board.

Subcommand Purpose
wp wcb migrate wpjm Import jobs from WP Job Manager
wp wcb migrate wpjm-resumes Import resumes from WP Job Manager Resume Manager (Pro features consume the imported resumes)

wp wcb scale

Production-readiness benchmarking. Per the team standard, every plugin must define hot-path query budgets and time them against a production-shape dataset.

Subcommand Purpose
wp wcb scale seed Generate a production-shape synthetic dataset (defaults: 10,000 candidates, 1,000 employers, 500 companies, 5,000 jobs; override per type with --candidates, --employers, etc.)
wp wcb scale benchmark Time the named hot-path queries; exit 1 if any exceeds its budget
wp wcb scale teardown Drop the synthetic rows (idempotent - flagged via usermeta, never touches genuine content)

Per-query budgets are defined in cli/class-scale-command.php (BUDGETS_MS), unchanged through 1.7.0: single-job read 5ms, applications-for-a-job 50ms, companies/candidates list-50 50ms, jobs list-50 100ms, location filter 150ms, keyword search 200ms.

Example - full benchmark cycle:

wp wcb scale seed && wp wcb scale benchmark && wp wcb scale teardown

The scale gate runs as stage 5.1 of composer ci. The first time you ship to production, run this against a clone of the production DB sized to your actual customer load.

wp wcb (top-level)

Utility subcommands on the root wcb command:

Command Purpose
wp wcb status Print a health summary (page mappings, capabilities, cron schedule, version)
wp wcb abilities List the registered Career Board abilities and whether a user is granted each (--user-id=<id>)

Ability gating

WP-CLI runs as the system user (no current-user context). The wp wcb abilities command resolves a list of Career Board capabilities against a target user (--user-id=<id>) so you can audit what a role can do. The wcb_cli_abilities filter extends the capability-to-label map that command reports on - it does not auto-gate other subcommands:

add_filter( 'wcb_cli_abilities', function ( $map ) {
    // Add your add-on's custom capability to the audit table.
    $map['my_addon_manage_things'] = 'Manage My Addon Things';
    return $map;
});

If your own subcommand needs to enforce a capability, call the base class helper inside the method:

$this->require_ability( 'wcb/moderate-jobs' );

Adding your own command

Use the same base class the plugin uses, WCB\Cli\AbstractCliCommand. Each public method becomes a subcommand (the standard WP-CLI convention):

namespace MyAddon;

use WCB\Cli\AbstractCliCommand;

class My_Command extends AbstractCliCommand {

    /**
     * ## EXAMPLES
     *
     *   wp wcb my-thing greet
     *
     * @param array<int,string>    $args       Positional args.
     * @param array<string,string> $assoc_args Flags.
     */
    public function greet( array $args, array $assoc_args ): void {
        // Optional ability gate (no-op when no user context is set).
        $this->require_ability( 'wcb/post-jobs' );

        \WP_CLI::success( 'Hello from my command' );
    }
}

if ( defined( 'WP_CLI' ) && WP_CLI ) {
    \WP_CLI::add_command( 'wcb my-thing', My_Command::class );
}

The base class extends \WP_CLI_Command and adds two abilities-aware helpers: check_ability( $ability ) (returns a bool) and require_ability( $ability ) (halts the command if the ability is not granted). See the wcb_cli_abilities filter below to map subcommands to abilities.

Extension Cookbook

Common things developers ask "how do I…" - with the smallest working snippet for each. Every recipe uses public hooks; nothing here forks the source.

Add a field to the apply form

You want candidates to fill in (say) a "LinkedIn URL" when applying.

// 1. Render the input inside the apply panel.
add_action( 'wcb_application_form_fields', function ( $job_id ) {
    ?>
    <label class="wcb-form-label">
        <span><?php esc_html_e( 'LinkedIn URL', 'my-addon' ); ?></span>
        <input type="url" name="my_addon_linkedin" class="wcb-field" />
    </label>
    <?php
});

// 2. Allow the field through the apply endpoint.
add_filter( 'wcb_application_form_fields_groups', function ( $groups, $job_id ) {
    $groups['my_addon'] = array(
        'fields' => array(
            'linkedin' => array( 'type' => 'url', 'sanitize' => 'esc_url_raw' ),
        ),
    );
    return $groups;
}, 10, 2 );

// 3. Read the saved value later - it's stored as `_wcb_application_field_linkedin`.
$url = get_post_meta( $app_id, '_wcb_application_field_linkedin', true );

Add a column to the admin applications table

add_filter( 'manage_wcb_application_posts_columns', function ( $cols ) {
    $cols['my_score'] = __( 'Score', 'my-addon' );
    return $cols;
});

add_action( 'manage_wcb_application_posts_custom_column', function ( $col, $post_id ) {
    if ( 'my_score' === $col ) {
        echo (int) get_post_meta( $post_id, '_my_score', true );
    }
}, 10, 2 );

Notify Slack when a job is posted

add_action( 'wcb_job_created', function ( $job_id, $request ) {
    $title = get_the_title( $job_id );
    wp_remote_post( SLACK_WEBHOOK_URL, array(
        'body' => wp_json_encode( array(
            'text' => sprintf( 'New job posted: *%s*', $title ),
        ) ),
        'headers' => array( 'Content-Type' => 'application/json' ),
        'blocking' => false,
    ));
}, 10, 2 );

Add a tab to the Settings page

add_filter( 'wcb_settings_tabs', function ( $tabs ) {
    $tabs['my_addon'] = __( 'My Addon', 'my-addon' );
    return $tabs;
});

add_action( 'wcb_settings_tab_my_addon', function () {
    settings_fields( 'my_addon_group' );
    do_settings_sections( 'my_addon_group' );
    submit_button();
});

Override the credit cost for a specific board

add_filter( 'wcb_board_credit_cost', function ( $cost, $board_id ) {
    if ( get_option( 'my_addon_premium_board' ) === $board_id ) {
        return 5; // Override the normal cost
    }
    return $cost;
}, 10, 2 );

Inject a step into the post-a-job wizard

The 4-step wizard fires wcb_job_form_step1_fieldswcb_job_form_step4_preview actions inside each step's container. Adding a fifth step takes a JS-side hook too - but injecting fields into an existing step is trivial:

add_action( 'wcb_job_form_step3_fields', function () {
    ?>
    <div class="wcb-form-field">
        <label class="wcb-form-label">
            <?php esc_html_e( 'Industry sub-category', 'my-addon' ); ?>
        </label>
        <select name="my_addon_subcat">
            <option value="frontend">Frontend</option>
            <option value="backend">Backend</option>
        </select>
    </div>
    <?php
});

Add a column to the REST jobs response

add_filter( 'wcb_rest_prepare_job', function ( $row, $post ) {
    $row['my_remote_friendly'] = (bool) get_post_meta( $post->ID, '_remote_friendly', true );
    return $row;
}, 10, 2 );

This propagates everywhere the jobs API is consumed - the listings block, the single-job page, third-party integrations.

Disable a built-in feature

Most Pro features are gated by wcb_pro_*_enabled filters. To turn off resume builder for a specific role:

add_filter( 'wcb_pro_resumes_enabled', function ( $enabled ) {
    if ( current_user_can( 'wcb_employer' ) ) {
        return false; // Hide resume tab from employers
    }
    return $enabled;
});

Different gateways for different user segments:

add_filter( 'wcb_credit_purchase_url', function ( $url ) {
    if ( current_user_can( 'wcb_employer_premium' ) ) {
        return '/premium-credits/';
    }
    return $url;
});

Restrict the boards dropdown by user role

add_filter( 'wcb_board_options_for_employer', function ( $options, $user_id ) {
    if ( ! user_can( $user_id, 'wcb_post_to_premium_boards' ) ) {
        // Drop any board whose id is in the "premium" list.
        $premium_ids = (array) get_option( 'my_premium_board_ids', array() );
        $options = array_filter( $options, fn( $o ) => ! in_array( (int) $o['id'], $premium_ids, true ) );
    }
    return $options;
}, 10, 2 );

(Pro's BP-groups integration uses this same filter to drop boards whose linked BuddyPress group the user is not a member of.)

Add a custom transactional email

The email registry holds email objects, not config arrays. Each one extends WCB\Modules\Notifications\AbstractEmail, declares its identity, and wires its own trigger hook in boot(). Register the object through the wcb_registered_emails filter and it appears automatically in Settings -> Emails (subject override, enable/disable toggle, and the send log all come for free).

use WCB\Modules\Notifications\AbstractEmail;

class My_Welcome_Email extends AbstractEmail {

    public function get_id(): string {
        return 'my_addon_welcome';
    }

    public function get_title(): string {
        return __( 'Welcome to the board', 'my-addon' );
    }

    public function get_recipient(): string {
        return __( 'New candidates', 'my-addon' );
    }

    public function get_default_subject(): string {
        return __( 'Welcome to our job board', 'my-addon' );
    }

    public function boot(): void {
        // Trigger off any Career Board action hook.
        add_action( 'wcb_candidate_registered', array( $this, 'handle' ), 10, 2 );
    }

    public function handle( int $user_id, $request ): void {
        $user = get_userdata( $user_id );
        if ( ! $user ) {
            return;
        }
        // send() respects the per-template enable toggle and writes the log row.
        $this->send( $user->user_email, array( 'name' => $user->display_name ), $user_id );
    }
}

add_filter( 'wcb_registered_emails', function ( array $emails ): array {
    $emails[] = new My_Welcome_Email();
    return $emails;
});

The base class gives you is_enabled(), get_subject() (with the admin override), and the protected send( $to, $vars, $user_id ) helper that dispatches and logs. Read modules/notifications/emails/class-email-job-approved.php for a complete working example.

Where to find the rest

Read 02-hooks-reference.md for the full inventory. For anything not covered by a hook, the next step is to extend a Career Board class directly - see 03-rest-api.md for the REST controller base class and the WP-CLI section in 04-wp-cli.md for the CLI base class.

Something unclear? Open a support ticket → · Refund policy

Buy WP Career Board