
WHMCS hooks are the simplest way to make WHMCS do something no setting can: add a tag to every client-area page, log something when an invoice is paid, or block an order that doesn’t meet a rule. You don’t need a full module for that. This guide explains how WHMCS hooks work, where they go and how to write one safely, with real examples we use ourselves.

What Are WHMCS Hooks?
A hook is a small piece of PHP code that WHMCS runs automatically when a specific event happens. WHMCS has hundreds of these events, called hook points: a client signs up, an invoice is paid, a service is created, a ticket is opened, a client-area page loads. You attach your own function to a hook point, and WHMCS calls it at that moment.
The big advantage of WHMCS hooks is that they change how WHMCS behaves without editing WHMCS’s own files. Core files get replaced every time you update. Hook files don’t, so your changes survive updates.
WHMCS Hooks vs. Addon Modules
A hook changes or reacts to something WHMCS already does. An addon module adds a whole new feature with its own settings page and interface. If you need a single behavior change, WHMCS hooks are usually enough. If you need new screens, settings or database tables, you’re looking at an addon module, which we cover in our WHMCS addon module guide. Many addon modules include hooks too.

Where Hook Files Go
Standalone hooks live in the /includes/hooks/ folder of your WHMCS install. WHMCS automatically loads every PHP file in that folder, so there’s nothing to register or switch on. Drop a file in and it’s live.
Hooks that belong to an addon module go in a hooks.php file inside that module’s folder. Those only load while the addon is activated, which makes them easy to turn off.
Give hook files clear, unique names, such as yourcompany_seo.php, so you know what each one does a year from now.
The Basic Structure of a Hook
Every hook uses the add_hook() function, which takes three things: the hook point name, a priority number and the function to run.
<?php
if (!defined('WHMCS')) {
die('This file cannot be accessed directly');
}
add_hook('InvoicePaid', 1, function ($vars) {
logActivity('Invoice #' . $vars['invoiceid'] . ' was paid.');
});
- The
defined('WHMCS')check stops anyone from loading the file directly in a browser. Always include it. 'InvoicePaid'is the hook point: this runs whenever an invoice is marked paid.1is the priority. If several hooks use the same hook point, lower numbers run first.$varsholds the information WHMCS passes in. ForInvoicePaid, that includes the invoice ID.logActivity()is a built-in WHMCS function that writes to the Activity Log, which is handy for testing.
The Three Kinds of WHMCS Hooks You’ll Use Most
WHMCS hooks fall into a few patterns. What your function should return depends on which kind you’re using.
1. Action hooks: react to an event
These run after something happens and don’t need to return anything. The InvoicePaid example above is one. Others you’ll see often:
ClientAdd: a new client account is created.AfterModuleCreate: a service has just been provisioned on the server.TicketOpen: a client opens a support ticket.DailyCronJob: runs once a day with the WHMCS cron, good for cleanup and reports.
2. Output hooks: add HTML to a page
These return a string of HTML that WHMCS inserts into the page. ClientAreaHeadOutput adds to the <head> of every client-area page, ClientAreaFooterOutput adds before the closing body tag, and AdminAreaHeadOutput does the same for the admin area.
Here’s one we use on our own site. It tells search engines not to index shopping cart pages, which are thin, duplicate pages Google doesn’t need:
<?php
if (!defined('WHMCS')) {
die('This file cannot be accessed directly');
}
add_hook('ClientAreaHeadOutput', 1, function ($vars) {
if ($vars['filename'] === 'cart') {
return '<meta name="robots" content="noindex, follow">';
}
return '';
});
The $vars array tells you which page is loading: filename is the PHP file (like cart or clientarea) and templatefile is the template being shown. We go much further with this in our WHMCS SEO guide, including a hook that fixes duplicate URLs with canonical tags.
3. Variable hooks: pass data to templates
The ClientAreaPage hook runs on every client-area page and lets you return an array of variables. WHMCS hands those to the template, so your theme can use them.
<?php
if (!defined('WHMCS')) {
die('This file cannot be accessed directly');
}
add_hook('ClientAreaPage', 1, function ($vars) {
return [
'supportHours' => 'Monday to Saturday, 24 hours a day',
];
});
Now {$supportHours} works in any client-area template file. Change the text once in the hook, and it updates everywhere.

Validation Hooks: Stop Something From Happening
Some hooks can block an action. For example, ShoppingCartValidateCheckout runs when a customer tries to check out. If your function returns an array of error messages, WHMCS shows them and stops the order. Return nothing, and checkout carries on. Hosts use this for things like fraud rules or requiring certain information before an order goes through.
Tips for Writing Hooks Safely
- Test on a staging copy first. Because WHMCS loads every file in the hooks folder, a single PHP error in one hook can break your whole client area, including checkout.
- Keep each file focused. One file per job makes problems easy to track down. To switch a hook off, just remove its file.
- Return the right thing. Output hooks return a string, variable hooks return an array, and action hooks don’t need to return anything.
- Use WHMCS’s own tools for data. Use the built-in database layer and the internal API (
localAPI()) instead of raw database queries, so you don’t skip WHMCS’s own safety checks. - Escape anything you output. If a hook prints data that came from a user or a URL, pass it through
htmlspecialchars()first. - Check the official list. The full set of hook points and the variables each one passes is in the WHMCS developer documentation.
Frequently Asked Questions
Do WHMCS hooks survive updates?
Yes. Updates replace WHMCS’s core files, not the files you add to /includes/hooks/. It’s still worth testing your hooks after a major update in case a hook point or its variables changed.
How do I turn off a hook?
Delete the file or move it out of the hooks folder. For hooks inside an addon module, deactivating the addon turns them off.
Can two hooks use the same hook point?
Yes. They all run, in order of their priority numbers. For output hooks, WHMCS combines what each one returns.
Need a Hook or Module Built?
If you’d rather have someone else write and test it, that’s what we do. From a single hook to a full custom WHMCS module, we build against WHMCS’s official APIs so it keeps working through updates. See all our WHMCS addons & modules, or tell us what you need.