WP Manifestindependent plugin directory
manifest / content / custom-wp-exam-plugin

Custom CBT Exam Engine

A custom wordpress exam plugin

by You · github.com/thedanielsdev/custom-wp-exam-plugin

2stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/thedanielsdev/custom-wp-exam-plugin/archive/refs/heads/master.zip

A custom-built (no third-party quiz plugin) Computer-Based Testing system for WordPress — MCQ-only exams, candidates log in with just an approved email (no WordPress account needed), one attempt per person, instant score on submit.

Install

  1. In WP-Admin go to Plugins → Add New → Upload Plugin, upload custom-cbt-exam.zip, then Activate.
  2. Activation creates 4 database tables and a signing secret used for candidate session tokens.

1. Create the exam

CBT Exams → Add New Exam in the WP-Admin sidebar. Fill in title/description and the Exam Settings box: duration, max violations before auto-submit, shuffle options, pass score, whether candidates see a right/wrong breakdown after submitting, and an open/close schedule. Publish it and note its ID (shown as a ready-made shortcode in the settings box).

2. Add questions

You have two ways to add MCQ questions:

One at a time: from the exam's edit screen, click "Add Question to this Exam", fill in the options and the correct answer, publish.

In bulk (recommended once you have more than a handful): use the standalone Admin Panel's Questions tab (see below). Paste one question per line in this format:

Question text | Option 1; Option 2; Option 3; Option 4 | Correct option | Points

Points is optional and defaults to 1. Example:

What is the basic unit of life? | Atom; Cell; Tissue; Organ | Cell | 1
What organ pumps blood around the body? | Lungs; Liver; Heart; Kidney | Heart | 1

The correct answer must match one of the listed options exactly (copy-paste it to be safe). You can also upload a .txt/.csv file in the same format instead of pasting.

3. Manage everything from one page — the standalone Admin Panel

Rather than relying on wp-admin's own menu (which can be broken on some hosts by caching plugins, security plugins, or mu-plugins outside this plugin's control), there's also a standalone admin panel that works as an ordinary page on your site:

  1. Create a new WordPress Page (e.g. "Exam Admin") — leave it out of your nav menu if you'd rather it not be publicly linked; it's gated by login either way.
  2. Add this shortcode to the page:
    [cbt_admin_panel]
  3. Visit that page while logged in as an Administrator/Editor. You'll see three tabs:
    • Candidates — paste emails or upload a CSV/txt file, see who's taken the exam, reset anyone
    • Questions — bulk-add questions, see and delete existing ones
    • Results — every attempt, score, pass/fail, and violation count

This panel only checks that you're logged in with edit permissions — it doesn't depend on wp-admin's menu registration, so it isn't affected by whatever might interfere with the classic wp-admin screens on a given host.

(The classic wp-admin screens — CBT Exams → Results and CBT Exams → Candidates — are still there too, in case they work fine on your setup. Use whichever is reliable for you.)

4. Publish the exam to candidates

Create a separate page for candidates (not the admin one) and add:

[cbt_exam id="123"]

No WordPress account needed. A candidate visits the page, types the email they applied with, and — if it's on the approved list for that exam and they haven't taken it yet — they're let straight in, one question at a time, with Next/Previous navigation and a Submit button on the final question.

Matching your theme

The plugin's CSS deliberately avoids imposing its own fonts or a heavy "app" look — it inherits your theme's base font and text colour, using flat borders rather than shadows or rounded cards. If you want to match your brand more closely, override these CSS custom properties from your theme's Additional CSS (Appearance → Customize → Additional CSS):

#cbt-exam-root, .cbt-admin-root {
  --cbt-accent: #yourbrandcolor;
  --cbt-accent-text: #ffffff;
  --cbt-border: #dddddd;
}

How the anti-cheat works

  • On Start, the browser is asked to enter fullscreen, on devices/browsers that support it. iOS Safari does not support requesting fullscreen for a page — this is a platform limitation, not a bug in the plugin. On iPhone/iPad, the exam simply runs without the fullscreen requirement, and "leaving fullscreen" is not counted as a violation there (since fullscreen was never entered to begin with). Tab-switching and window-blur detection still work normally on iOS.
  • Switching tabs or the window losing focus each log a violation to the server.
  • Right-click, copy, cut, and paste are blocked client-side.
  • When violations reach the exam's configured threshold, the server force-submits the attempt — this can't be bypassed client-side, since the server independently tracks and enforces the count.
  • The countdown timer is server-authoritative: the client displays a countdown based on the server's expiry time, but the server independently rejects/finalizes any attempt whose time has expired, so changing the browser clock doesn't extend time.

One attempt only

Each candidate's email is tied to a specific exam with a "has taken" flag. The moment an attempt is submitted (manually, by timeout, or by hitting the violation limit), that flag is set — the server refuses to issue a new attempt for that email/exam again, even from a different browser or device. Use the Reset button next to a candidate's row if you ever need to let someone retake it.

Scoring

Everything is MCQ, so grading is instant. If "show breakdown" is turned on for the exam, candidates see their score, pass/fail, and a per-question right/wrong readout right after submitting. If it's off, they only see the final score.

Notes on scale

Built for roughly 20 candidates: plain custom MySQL tables via $wpdb, a REST polling interval of 15s, no caching layer. Comfortably handles far more than that without changes.