Sooner or later you will want WHMCS to do something it does not do out of the box: notify Slack on new orders, add a menu link, block certain email domains at signup. Editing WHMCS core files breaks on every update. Hooks are the supported way to run your own PHP code at specific points.
Before you start
- FTP or SSH access to the WHMCS directory and basic PHP knowledge.
- A staging copy of WHMCS for testing; a broken hook can stop the client area.
How hooks work
WHMCS fires named events – such as InvoicePaid, ClientAdd, AfterModuleCreate or ClientAreaPrimaryNavbar. Any PHP file in includes/hooks/ can register a function for an event with add_hook(). WHMCS loads all files in that folder on every request and runs your function when the event happens, passing relevant data such as the invoice ID.
Create your first hook
- Create
includes/hooks/notify_paid.php. - Add a function for the
InvoicePaidevent that logs the invoice ID:
<?php add_hook('InvoicePaid', 1, function ($vars) { logActivity('Custom hook: invoice ' . $vars['invoiceid'] . ' paid'); });- Pay a test invoice and check Utilities → Logs → Activity Log for your entry.
The number 1 is the priority – lower numbers run first when several functions use the same hook.
Useful hook points
| Hook | Typical use |
|---|---|
ClientAreaPrimaryNavbar | Add or remove client area menu items |
ClientDetailsValidation | Reject disposable email domains at signup |
AfterShoppingCartCheckout | Send new-order notifications to chat |
InvoicePaid | Sync payments to accounting software |
AfterModuleCreate | Extra setup after an account is provisioned |
DailyCronJob | Your own daily maintenance tasks |
The WHMCS developer documentation lists all hooks and the variables each one receives.
Use the WHMCS API inside hooks
Inside hooks you can call internal API functions with localAPI('GetClientsDetails', ['clientid' => $id]) – no credentials needed. For database access, use WHMCS's Capsule (Laravel query builder) rather than raw queries.
Debugging
- Use
logActivity()to write messages to the Activity Log. - Enable Display Errors briefly on staging to see PHP errors; see System Health and logs.
- If a hook breaks the site, rename the file (for example to
.php.off) to disable it instantly.
Keep it upgrade-safe
- Hooks in
includes/hooks/survive updates, but test them after each WHMCS upgrade. - Prefix function names or use closures to avoid conflicts.
- Never store secrets in hook files inside the web root without protection; read them from
configuration.phpor environment variables.
