For support, visit: wilcosky.com/contact
A comprehensive Applicant Tracking System built as a WordPress theme, featuring resume parsing, candidate management, requisition workflows, gamification, and embeddable job listings.
- Installation
- Initial Setup
- User Roles & Permissions
- Resume Parsing
- Requisition Management
- Candidate Management
- Public Job Listings
- Embed System
- Gamification System
- Settings & Configuration
- Testing the System
- Troubleshooting
- WordPress 5.0 or higher
- PHP 7.4 or higher
- MySQL 5.6 or higher
- Required PHP extensions:
gdorimagick(for image processing)mbstring(for text processing)zip(for file handling)xml(for PDF parsing)
If you don't have WordPress installed:
- Download WordPress from wordpress.org
- Extract and upload to your web server
- Create a MySQL database for WordPress
- Run the WordPress installation wizard
- Complete the initial WordPress setup
- Upload the
Adatheme folder to/wp-content/themes/ - Log in to your WordPress admin dashboard
- Navigate to Appearance > Themes
- Find "Ada" in the theme list
- Click Activate
After activation:
- Go to Settings > Permalinks
- Click Save Changes (even if you don't change anything)
- This registers the custom ATS routes (
/ats/*)
- Visit
http://yoursite.com/wp-admin/themes.php?page=ada-theme-settings - You should see the Ada Settings page
- If you see a 404, go to Settings > Permalinks and save again
Navigate to Appearance > Ada Settings (or directly to wp-admin/themes.php?page=ada-theme-settings).
- Logo: Upload your company logo (recommended: 45px height)
- Favicon: Upload a favicon for browser tabs
- Timezone: Set your timezone for accurate timestamps
- Cloudflare Turnstile (optional):
- Site Key: Your Turnstile site key
- Secret Key: Your Turnstile secret key
- Leave blank if not using Turnstile (for development/testing)
Configure the fields that appear on public job application forms:
- Default Fields: Name, Email, Phone, Cover Letter, Resume
- Add Custom Fields: Click "Add Field" to add text, textarea, select, checkbox, or file upload fields
- Field Options:
- Type: text, email, textarea, select, checkbox, file
- Label: Display name for the field
- Name: Internal field name (lowercase, no spaces)
- Required: Check if field is mandatory
Configure the fields that appear when submitting new requisitions:
- Default Fields: Job Title, Location, Department, Salary Range, Job Description
- Add Custom Fields: Same options as Application Form
- Note: Job Title and Job Description are always required
Configure the status workflow for candidates:
- Default Statuses: New, Screen, Interview, Offer, Hired, Rejected
- Add Status: Click "Add Status" to create new statuses
- Add Steps: Each status can have sub-steps (e.g., Interview can have Interview 1, Interview 2, Interview 3)
- Reorder: Drag statuses to reorder them
- Status Options:
- Name: Display name (e.g., "Phone Screen")
- Slug: Internal identifier (e.g., "phone_screen")
Configure the points system for recruiters:
- Points Map: Set points awarded for each action:
hourly: Points per hour logged in (default: 1)candidate_reviewed: Points for reviewing a candidate (default: 0.5)status_progression: Points for moving a candidate forward (default: 0.5)- Custom status points: Points for moving to specific statuses
- Spend Points Email: Email address to receive notifications when recruiters spend points
Configure the embed system for external job listings:
- API Key: Generate a unique API key for embed authentication
- Whitelist Domains: Add domains allowed to embed your jobs (one per line)
- Example:
example.com,jobs.example.com - Leave blank to allow all domains (not recommended for production)
- Example:
Customize the retro terminal aesthetic:
- Colors: Adjust color scheme
- Font: Choose font family
- Scanlines: Toggle scanline effect
Navigate to Users > Add New to create user accounts for your team.
- Username: Choose a unique username
- Email: Enter a valid email address
- Password: Set a strong password (or let WordPress generate one)
- Role: Select one of the following:
- Administrator: Full access to WordPress and ATS
- Editor: Full ATS access (can manage all candidates and requisitions)
- Recruiter: Can manage candidates, update statuses, view requisitions
- Hiring Manager: Can view candidates, create and edit requisitions
- ATS Approver: Can approve requisitions and assign recruiters
- Click Add New User
After creating a user, you can change their role:
- Go to Users > All Users
- Find the user
- Click Edit
- Change the Role dropdown
- Click Update User
WordPress Role: administrator
Capabilities:
- ✅ Full WordPress access
- ✅ Manage all ATS settings
- ✅ Create, edit, delete candidates
- ✅ Create, edit, delete requisitions
- ✅ Approve requisitions
- ✅ Assign recruiters
- ✅ Update candidate statuses
- ✅ Manage gamification settings
- ✅ View all data
Use Case: Site owners, IT administrators, system managers
WordPress Role: editor
Capabilities:
- ✅ Manage all ATS settings
- ✅ Create, edit, delete candidates
- ✅ Create, edit, delete requisitions
- ✅ Approve requisitions
- ✅ Assign recruiters
- ✅ Update candidate statuses
- ✅ Manage gamification settings
- ✅ View all data
- ❌ Limited WordPress access (no plugin/theme management)
Use Case: HR managers, ATS administrators who need full ATS control without WordPress admin access
WordPress Role: ada_recruiter
Capabilities:
- ✅ View all candidates
- ✅ Edit all candidates (including others' candidates)
- ✅ View all requisitions
- ✅ Edit requisitions
- ✅ Update candidate statuses
- ✅ Screen candidates
- ✅ Move candidates to interview
- ✅ Move candidates to offer
- ✅ Hire candidates
- ✅ Rate candidates (star ratings)
- ✅ Add notes and timeline events
- ✅ Assign tags to candidates
- ✅ View and earn points
- ❌ Cannot delete candidates
- ❌ Cannot submit requisitions
- ❌ Cannot approve requisitions
- ❌ Cannot assign recruiters
- ❌ Cannot manage settings
Use Case: Recruiters who actively manage candidates through the hiring process
Access Points:
- Dashboard:
/ats/dashboard - Candidates:
/ats/candidates - Candidate Details:
/ats/candidate/{id} - Requisitions:
/ats/requisitions - Requisition Details:
/ats/requisition/{id} - Points:
/ats/points
WordPress Role: ada_hiring_manager
Capabilities:
- ✅ View all candidates
- ✅ View all requisitions
- ✅ Create new requisitions
- ✅ Edit requisitions
- ❌ Cannot edit candidates
- ❌ Cannot update candidate statuses
- ❌ Cannot approve requisitions
- ❌ Cannot assign recruiters
- ❌ Cannot manage settings
Use Case: Department managers who need to create job postings and view applicants
Access Points:
- Dashboard:
/ats/dashboard - Candidates:
/ats/candidates(view only) - Candidate Details:
/ats/candidate/{id}(view only) - Requisitions:
/ats/requisitions - Requisition Details:
/ats/requisition/{id} - Submit Requisition:
/ats/submit-requisition
WordPress Role: ada_approver
Capabilities:
- ✅ View all requisitions
- ✅ Edit requisitions
- ✅ Approve requisitions
- ✅ Assign recruiters to requisitions
- ❌ Cannot view candidates
- ❌ Cannot create requisitions
- ❌ Cannot manage settings
Use Case: HR directors or executives who approve job postings and assign recruiters
Access Points:
- Dashboard:
/ats/dashboard - Requisitions:
/ats/requisitions - Requisition Details:
/ats/requisition/{id}
The Ada ATS automatically parses uploaded resumes to extract:
-
Contact Information:
- Name (from header section)
- Email address
- Phone number
-
Skills:
- Programming languages (JavaScript, Python, Java, etc.)
- Frameworks (React, Angular, Django, etc.)
- Design tools (Photoshop, Figma, etc.)
- Business tools (Excel, Salesforce, etc.)
- Soft skills (Leadership, Communication, etc.)
- Industry-specific skills (Accounting, Healthcare, etc.)
-
Extracted Text:
- Full text content of the resume
- Preserved formatting and structure
- Available for search and review
- PDF (
.pdf): Text-based and image-based PDFs- Uses Smalot/PdfParser library for extraction
- Word Documents:
.docx(Word 2007+): Full support via ZIP/XML extraction.doc(Word 97-2003): Basic support via text extraction (may have limitations with complex formatting)
When a candidate uploads a resume:
- Upload: File is uploaded to WordPress media library
- Parse: System extracts text using appropriate parser (PDF or Word)
- Extract Contact Info: Name, email, and phone are identified
- Extract Skills: Comprehensive skill patterns are matched against resume text
- Store: All data is saved to the candidate profile
- Auto-fill: Application form fields are automatically populated
During resume upload, candidates see real-time progress:
- "Uploading resume..."
- "Resume uploaded."
- "Parsing resume..."
- "Saving extracted text..."
- "Pulling out skills..."
- "Looking at the application fields..."
- "These fields were detected: [list]"
- "I see a name in the extracted resume text..."
- "Populating the name field..."
- "I see an email..."
- "Populating the email field..."
- "I see a phone number..."
- "Populating the phone field..."
- "Success!"
On the candidate detail page (/ats/candidate/{id}):
- Extracted Text: Scrollable box showing the full parsed resume text
- Tags: Automatically extracted skills displayed as tags
- Contact Info: Name, email, and phone (if extracted)
If parsing fails:
- Check File Format: Ensure file is PDF or Word document
- Check File Size: Large files (>10MB) may timeout
- Check File Type: Image-only PDFs may not parse correctly
- Check Server Logs: Review PHP error logs for parsing errors
- Check PHP Extensions: Ensure required extensions are installed
- Submit: Hiring Manager or Admin creates a requisition
- Pending: Requisition awaits approval
- Approved: ATS Approver approves the requisition
- Assign Recruiter: ATS Approver assigns a recruiter (optional)
- Post: Requisition becomes visible on public job listings
- Close: Requisition is closed (no longer accepting applications)
Who Can Create: Hiring Managers, Administrators, Editors
Steps:
- Navigate to
/ats/submit-requisition(or click "New Requisition" in sidebar) - Fill in required fields:
- Job Title: Position title
- Location: Job location
- Department: Department name
- Salary Range: Salary range (e.g., "$50,000 - $70,000" or "50k-70k")
- Job Description: Full job description (rich text editor)
- Add custom fields (if configured in settings)
- Click Submit Requisition
Status After Submission: pending
Who Can Approve: ATS Approvers, Administrators, Editors
Steps:
- Navigate to
/ats/requisitions - Find the requisition with status "Pending"
- Click on the requisition to view details
- Click Approve Requisition
- (Optional) Assign a recruiter from the dropdown
- Click Save
Status After Approval: approved (visible on public listings) or approved_unposted (not visible)
Who Can Assign: ATS Approvers, Administrators, Editors
Steps:
- Open the requisition detail page
- Find the "Assigned Recruiter" field
- Select a recruiter from the dropdown
- Click Save
Note: Recruiters can view all requisitions regardless of assignment. Assignment is for organizational purposes.
Who Can Add: Anyone who can edit requisitions
Steps:
- Open the requisition detail page
- Scroll to "Knockout Questions" section
- Click Add Question
- Enter:
- Question: The question text
- Options: Multiple choice options (one per line)
- Correct Answer: The correct answer option
- Click Save
How It Works:
- Knockout questions appear on the public application form
- If a candidate answers incorrectly, they are automatically rejected for that requisition
- The application is still submitted, but status is set to "rejected"
- A timeline note is added: "Rejected due to answering '[answer]' to the knockout question '[question]'"
- Candidates are not shown an error message (application appears successful)
- Pending: Awaiting approval
- Approved: Approved and visible on public listings
- Approved - Unposted: Approved but not visible on public listings
- Closed: No longer accepting applications
Navigate to /ats/requisitions to see:
- Requisition number
- Job title
- Location
- Department
- Status
- Number of candidates
- Assigned recruiter
Filters:
- Requisition ID
- Status
- Location
- Department
Click on a requisition to view:
- Details:
- Job Title
- Hiring Manager
- Assigned Recruiter
- Location
- Department
- Salary Range
- Status
- Job Description: Full formatted description
- Knockout Questions: List of questions and correct answers
- Candidates Table: All candidates who applied to this requisition
- Name
- Phone
- Status (per-requisition)
- Resume (View link)
- Applied Date
Candidates have per-requisition statuses, meaning the same candidate can have different statuses for different jobs they applied to.
Example:
- Candidate applies to Job A → Status: "New"
- Candidate applies to Job B → Status: "Interview"
- On Job A detail page: Status shows "New"
- On Job B detail page: Status shows "Interview"
- New: Initial status when candidate applies
- Screen: Candidate has been screened
- Interview: Candidate is in interview process
- Sub-steps: Interview 1, Interview 2, Interview 3
- Offer: Offer has been extended
- Hired: Candidate has been hired
- Rejected: Candidate has been rejected
- Go to Appearance > Ada Settings > Candidate Statuses
- Add Status: Click "Add Status"
- Add Steps: Click "Add Step" within a status
- Reorder: Drag statuses to change order
- Edit: Click on status name or slug to edit
- Click Save Changes
Navigate to /ats/candidates to see:
- Candidate name
- Phone
- Tags (skills)
- Rating (star rating average)
- "Incomplete Application" badge (if applicable)
- Applied date
Filters:
- Search: Search by name, email, phone, tags, or parsed resume text
- Supports boolean operators:
AND,OR,NOT,+term,-term,(term) - Example:
JavaScript AND React OR Vue
- Supports boolean operators:
- Requisition: Filter by requisition
- Tags: Filter by tags
Navigate to /ats/candidate/{id} to view full candidate information.
- Basic Info: Name, email, phone
- Resume: View/download resume
- Parsed Resume Text: Scrollable box with extracted text
- Tags: Skills extracted from resume (click to remove)
- Rating: Star rating (average of all recruiter ratings)
- Assigned Recruiter: Currently assigned recruiter
- Requisition Dropdown: Select a requisition to view candidate's status for that requisition
- Status: Current status for selected requisition
- Timeline: Activity history for selected requisition
- Select a requisition from the dropdown
- Use the Status dropdown to change status
- Click Update Status
- A timeline event is automatically added
- Scroll to "Notes" section
- Enter note in rich text editor
- Click Add Note
- Note appears in timeline
- Click stars (1-5) to rate candidate
- Rating is saved immediately
- Displayed rating is the average of all recruiter ratings
- Scroll to "Tags" section
- Enter tags in the input field (comma-separated)
- Click Save Tags
- Tags are added to candidate profile
Note: Tags input is for adding new tags only. Existing tags are displayed above the input.
- Scroll to "Assigned Recruiter" section
- Select recruiter from dropdown
- Click Save
- Scroll to "Resume" section
- Click Choose File
- Select PDF or Word document
- Click Upload Resume
- Resume is parsed automatically
- Tags are updated with extracted skills
- Parsed text is updated
Note: Uploading a new resume does not change the candidate's status.
On the candidates list page (/ats/candidates):
- Select candidates using checkboxes
- Choose action from "Bulk Actions" dropdown:
- Update Status: Change status for multiple candidates
- Assign Recruiter: Assign recruiter to multiple candidates
- Assign Requisition: Link candidates to a requisition
- Delete: Delete candidates (Administrators only)
- Click Apply
If a candidate uploads a resume but doesn't complete the application form, they are marked as "Incomplete Application".
Identifying Incomplete Applications:
- Badge appears on candidate list: "⚠ Incomplete Application"
- Notice appears on candidate detail page
Alerting Candidates:
- On candidate detail page, find "Incomplete Application" notice
- Click Alert Candidate
- Confirm in dialog
- Email is sent to candidate with:
- Subject: "Incomplete Application"
- Body: Link to public job posting and application form
Completing Incomplete Applications:
- Candidate can return and complete the application
- If they submit with the same name/email for the same requisition, their existing candidate profile is updated (not duplicated)
Navigate to /ats/jobs to see the public job listings page.
Features:
- List of all approved requisitions
- Search by keyword
- Filter by location, department, salary range
- Click on job to view details and apply
Navigate to /ats/job/{id} to view a specific job posting.
Features:
- Full job description
- Location, department, salary range
- Application form
- Resume upload with parsing
- Auto-filled fields after resume upload
- View Job: Candidate views job posting
- Upload Resume (optional):
- Click "Upload Resume"
- Select PDF or Word document
- Watch step-by-step parsing progress
- Fields auto-populate with extracted contact info
- Complete Form: Fill in any remaining fields
- Answer Knockout Questions: If applicable
- Submit: Click "Submit Application"
After Submission:
- Candidate sees success message
- Application is saved (even if knockout questions failed)
- If knockout questions failed, candidate status is set to "rejected" for that requisition
- Timeline note is added with rejection reason
The system checks for duplicate applications based on:
- Email address
- Name (exact match)
- Requisition ID
If Duplicate Found:
- If existing application is incomplete, it is updated (not duplicated)
- If existing application is complete, candidate sees error: "You have already applied for this position"
The embed system allows you to display job listings and application forms on external websites using a simple JavaScript snippet.
- Go to Appearance > Ada Settings > Embed Settings
- Generate API Key: Click "Generate" to create a unique API key
- Whitelist Domains: Add domains allowed to embed your jobs (one per line)
- Example:
example.com - Leave blank to allow all domains (not recommended)
- Example:
- Go to Appearance > Ada Settings > Embed Settings
- Copy the embed snippet displayed on the page
- Paste into your external website's HTML
<script type="text/javascript">
(function() {
var adaEmbed = document.createElement('script');
adaEmbed.type = 'text/javascript';
adaEmbed.async = true;
adaEmbed.src = 'https://yoursite.com/wp-content/themes/Ada/public/js/embed.js';
adaEmbed.setAttribute('data-api-url', 'https://yoursite.com/wp-json/ada/v1/');
adaEmbed.setAttribute('data-api-key', 'YOUR_API_KEY');
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(adaEmbed, s);
})();
</script>- Job Listings: Display all approved jobs
- Search: Search jobs by keyword
- Filters: Filter by location, department, salary range
- Job Details: View full job description
- Application Form: Complete application inline (not in modal)
- Resume Parsing: Same step-by-step parsing as main site
- Auto-fill: Fields auto-populate after resume upload
The embed will automatically create a container element. You can style it with CSS:
.ada-embed-container {
/* Your custom styles */
}- Embed requests are validated against whitelisted domains
- API key is required for authentication
- Nonce validation is optional for embeds (handled by whitelist)
The gamification system awards points to recruiters for various actions, encouraging engagement and productivity.
Points are awarded for:
- Hourly Login: 1 point per hour logged in (default)
- Candidate Reviewed: 0.5 points per candidate reviewed (default)
- Status Progression: 0.5 points per status change (default)
- Custom Status Points: Configurable points for moving to specific statuses
- Navigate to
/ats/points - View:
- Current points balance
- Points history (transactions)
- Points earned per action
Recruiters can "spend" points to request rewards:
- Navigate to
/ats/points - Enter points to spend
- Enter message/request
- Click Spend Points
- Email is sent to admin (configured in Gamification settings)
- Go to Appearance > Ada Settings > Gamification
- Set points for each action:
hourly: Points per hourcandidate_reviewed: Points per reviewstatus_progression: Points per status change- Custom status slugs: Points for specific statuses
- Set Spend Points Email: Email to receive spending requests
- Click Save Changes
Navigate to Appearance > Ada Settings to access all configuration options.
- Points map (points per action)
- Spend points email
- Custom fields for requisition submission
- Field types: text, textarea, select, checkbox, file
- Custom fields for public application forms
- Field types: text, email, textarea, select, checkbox, file
- Configure status workflow
- Add/edit statuses and sub-steps
- Reorder statuses
- API key generation
- Domain whitelist
- Color customization
- Font selection
- Scanline effect toggle
- Logo upload
- Favicon upload
- Timezone setting
- Cloudflare Turnstile keys
- Email templates (future feature)
Follow this complete workflow to test all features:
- Create a Hiring Manager user
- Create a Recruiter user
- Create an ATS Approver user
- Log in as Hiring Manager
- Navigate to
/ats/submit-requisition - Fill in job details
- Submit requisition
- Verify status is "Pending"
- Log in as ATS Approver
- Navigate to
/ats/requisitions - Open the pending requisition
- Click Approve Requisition
- Assign a recruiter
- Verify status is "Approved"
- Still on requisition detail page
- Add a knockout question:
- Question: "Do you have 5+ years of experience?"
- Options: "Yes", "No"
- Correct Answer: "Yes"
- Save
- Log out
- Navigate to
/ats/jobs - Click on the job
- Upload a resume (PDF or Word)
- Watch parsing progress
- Verify fields auto-populate
- Complete application form
- Answer knockout question incorrectly
- Submit application
- Verify success message
- Log in as Recruiter
- Navigate to
/ats/candidates - Find the candidate
- Verify "Incomplete Application" badge (if applicable)
- Click on candidate
- Verify:
- Parsed resume text is visible
- Tags are extracted
- Status is "rejected" (due to knockout question)
- Timeline shows rejection reason
- Select requisition from dropdown
- Change status to "Screen"
- Add a note
- Rate candidate (3 stars)
- Add a tag
- On candidates page, use search:
- Search by name
- Search by email
- Search by tag (e.g., "JavaScript")
- Search by parsed resume text
- Test boolean operators:
JavaScript AND React
- Select multiple candidates
- Update status for all
- Assign recruiter to all
- As recruiter, navigate to
/ats/points - Verify points are awarded for actions
- View points history
- Test spending points
- Go to Appearance > Ada Settings > Embed Settings
- Generate API key
- Add test domain to whitelist
- Copy embed code
- Create test HTML page with embed code
- Verify jobs load
- Test search and filters
- Test application submission
Cause: Trying to access ATS pages without logging in
Solution: Log in to WordPress, then access ATS pages
Cause: Permalinks not flushed after theme activation
Solution: Go to Settings > Permalinks and click Save Changes
Causes:
- Unsupported file format
- File is image-based PDF (no text layer)
- PHP extensions missing
- File too large
Solutions:
- Ensure file is PDF or Word document
- Check PHP error logs
- Verify PHP extensions are installed
- Try smaller file (<10MB)
Causes:
- Nonce expired
- Cloudflare Turnstile misconfigured
- Caching issues
Solutions:
- Refresh page and try again
- Clear browser cache
- Check Turnstile keys in settings
- Disable Turnstile for testing (leave keys blank)
Cause: Data corruption or migration issue
Solution: This should be automatically fixed. If not, contact support.
Causes:
- Search term too specific
- Boolean operator syntax error
- Data not indexed
Solutions:
- Try simpler search terms
- Check boolean syntax:
term1 AND term2, notterm1&term2 - Verify candidate has tags or parsed resume text
Causes:
- Domain not whitelisted
- API key incorrect
- CORS issues
Solutions:
- Verify domain is in whitelist (no
http://orhttps://) - Check API key matches settings
- Check browser console for CORS errors
Causes:
- Points map not configured
- WP-Cron not running
- User role incorrect
Solutions:
- Check Gamification settings
- Verify WP-Cron is enabled
- Ensure user has
ada_recruiterrole
- Check Error Logs: Review PHP error logs and WordPress debug log
- Check Browser Console: Open browser developer tools (F12) and check for JavaScript errors
- Verify Permissions: Ensure user has correct role and capabilities
- Test in Incognito: Rule out browser cache/cookie issues
- Check WordPress Version: Ensure WordPress is up to date
- Check PHP Version: Ensure PHP 7.4+ is installed
- All ATS pages require login (except public job listings)
- Public application endpoints validate nonces and Turnstile (if configured)
- Embed system uses domain whitelisting and API keys
- All user input is sanitized and escaped
- File uploads are validated and stored securely
- Resume parsing is performed server-side
- Large files may take time to parse
- Search uses WordPress meta queries (optimized)
- Points system uses WP-Cron for hourly awards
- Candidates: Custom post type
ada_candidate - Requisitions: Custom post type
ada_requisition - Resume files: WordPress media library
- Parsed text: Post meta
ada_parsed_resume_text - Tags: Post meta
ada_tags - Status: Post meta
ada_status_requisition_{id}(per-requisition) - Timeline: Post meta
ada_timeline_requisition_{id}(per-requisition) - Points: User meta
ada_points
- Resumes are automatically deleted when candidate is deleted
- Orphaned resumes (not linked to any candidate) are cleaned up daily via WP-Cron
- Timeline events are stored indefinitely (no automatic cleanup)
For issues, questions, or feature requests, please contact the theme developer or submit an issue through the appropriate channel.
Version: 1.0.0
Last Updated: 2025
Author: Billy Wilcosky
License: Proprietary