Free WHMCS Action Hooks Factory • Open Source by Katamaze

Back   Posted on 27 april 2020 / Updated on 14 november 2022
Reading time 28 minutes

WHMCS as Fast as Possible

It's much easier to understand what is WHMCS making a parallelism with WordPress. Of the many free CMS, WordPress is the best and most popular solution to start a blog. WHMCS is the same in its reference market. It's the way go to start an hosting business for providers, web agencies and IT professionals.

Both systems are the undisputed market leaders in their respective field. WordPress reaches 60% of market share. WHMCS attracts about 50.000 customers worldwide. They are both flexible and can accommodate several businesses needs. In them there's more than a control panel and a blogging platform.

That said, similarities end here. WordPress is free, open source and good at many things. WHMCS kicks off at 15.95 $ per month. Source code is obfuscated and even if it is a solid platform, WHMCS is not perfect.

Continue reading our beginners guide to WHMCS and common mistakes to avoid in WHMCS for more details.

Understanding Action Hooks

Action Hooks allow you to execute your own code when events occurr inside WHMCS. With them you can achieve impressive results.

For example we managed to transform WHMCS into a CMS like WordPress with full support for Search Engine Optimization. We've also introduced new billing concepts (monthly invoicing, electronic invoicing, credit notes) and Affiliate Marketing.

As you can see you can there's no limit to imagination. If you're new to WHMCS and Action Hooks, please refer to documentation:

Perfect Your WHMCS

Over the years we coded thousand of action hooks most of which are part of our WHMCS modules.

In this post that is available also on Github we share a collection of action hooks for free that you can copy/paste on your WHMCS site. You can also adapt them to your specific needs or use as inspiration for your projects.

The point of this this project is to help Developers, Hosting Providers, Web Agencies and IT professionals to perfect WHMCS. We are continually adding and improving hooks. It would be great if could you join us on Github!

Free Hooks Collection

This post contains in-depth instructions and previews. It is also available in italian language. We are always willing to code new hooks based on your feedback so feel free to comment and ask for new ones.

Scripts are provided free of charge "as is" without warranty of any kind. You're not allowed to remove copyright notice. Let's start!

Admin Stats for WHMCS v8

As you probably know WHMCS v8 no longer provides statistics on top of the page about pending orders, overdue invoices and tickets awaiting reply. This action hook adds them back to interface as you can see from the following screenshots.

The one thing you can customize is $showZero variable. Let's focus on the 0 Ticket(s) Awaiting Reply badge of above images. If $showZero is set to false, the widget doesn't show this specific badge.

This widget is fully responsive and appears if there's at least one pending order, overdue invoice or ticket awaiting reply. If there's nothing to show it disappears. To avoid any possibility of confusion, the hook automatically detects if you're running v8.

Get the Code

Client Group Color in Ticket View for WHMCS v8

Client group background colors no longer display on ticket view page. Go figure out why WHMCS decided to remove it from v8. This action hook puts the styling back.

Get the Code

Simulate / Run WHMCS Daily Cron Job on Demand

As the name suggests, WHMCS daily cron job runs once per day. There's no easy way to make it run multiple times. This could be frustrating in case you're coding or testing new features that's where this hook comes to help.

The hook adds Run Daily Cronjob button (the orange one) on top of your WHMCS Administration. Clicking it allows to run WHMCS daily cron job whenever you want. All it takes is a click. Please, ignore Reinstall and Manage Demo buttons. We use them for Live Demo to let visitors try our modules before purchase.

Be advised that on WHMCS v8 and newer versions the *Run Daily Cronjob* button is placed on top of the sidebar as shown in the screenshot.

Get the Code

Accept Quote without Logging In

When you send a quote, WHMCS forces customers to login in order to accept it. This hook allows them to accept without the need to login. Every time the Quote Delivery with PDF mail is sent, the hook overrides {$quote_link} with a new link that contains an hash that ensures the authenticity of the request. This way only the recipient can accept the quote.

When the visitor clicks the link, the quote is automatically accepted and he/she sees the following modal on screen.

Get the Code

Bulk Auto Recalculate Client Domain & Products/Services

Yes, WHMCS integrates Bulk Pricing Updater but it works for all existing customers. Sometimes you simply need to recalculate prices for domains and products/services of a specific customer. This hook allows to do that in one click. First it adds the following button in client Summary.

Second it shows this modal on screen where you can freely choose to auto-recalculate domains or products/services.

Get the Code

cPanel & Plesk login button in My Services

Managing multiple hosting accounts could be frustrating for customers. The following hook makes things easier allowing them to login to any control panel directly from My Services list. Here's the preview.

The hook works with any panel (cPanel, Plesk, DirectAdmin, Centova Cast...) provided that servers and products/services have been integrated correctly. Before you get the code, keep in mind that this action hook requires some changes to a template file.

Open templates/{YOUR_TEMPLATE}/clientareaproducts.tpl and add the new Manage column in thead like follows.

        <th class="responsive-edit-button" style="display: none;"></th>

Your thead could be slightly different (eg. your first column could be the SSL icon check) so change things accordingly. Next move to tbody and add the cell right inside {foreach} loop.

<td class="text-center">
	{if $kt_autologin[$]}
	<div class="btn-group btn-group-sm plesk-login" style="width:60px;">
		<a href="clientarea.php?action=productdetails&id={$}&autologin=1" target="_blank" class="btn btn-primary btn-xs" alt="Click to Login" title="Click to Login" style="padding: 2px 5px;"><img src="templates/{$template}/img/katamaze_autologin/{$kt_autologin[$]->type}.png" style="height:22px; max-width:39px"> <i class="fa fa-sign-in fa-fw" aria-hidden="true"></i></a>

We suggest you to replace Click to Login with $LANG variable for multi-language support. Now we need to disable sorting for the newly added column. On top of the file you'll find the following statement.

{include file="$template/includes/tablelist.tpl" tableName="ServicesList" noSortColumns="4" filterColumn="3"}

Focus on noSortColumns="4". 4 means that the 5th column will be not sortable (column count start from zero). Change it accordingly. For example if your template uses the SSL check as 1st column, use noSortColumns="0, 5".

Get the Code

Related Service in Ticket Sidebar

Customers can specify the related service/domain on ticket submission but once the ticket has been sent the information is no longer visible. This hook makes sure that related service is always included in ticket sidebar (if specified).

Get the Code

Force Payment Gateway depending on Invoice Balance

It doesn't matter what payment method you use. It can be PayPal, Stripe, Skrill or Credit Card. The typical gateway charges absurdly high fees to manage your money. Billing Extension helps you saving up to 18% on transaction fees but such costs can be lowered even further.

Let's face it. In an ideal world we would be receiving money just with Bank Transfer (aka Wire Transfer) since it doesn't cost you anything. The following hook can be used to force the most convenient gateway you have depending on invoice balance. For example if invoice balance >= 1000 euro force banktransfer. Let's do some math.

  • PayPal charges 3.4% + 0.35 € per transaction meaning that receiving 1000 € costs you 35.35 €
  • Let's suppose on a yearly basis you receive 10 payments of 1000 €
  • At the end of the year you gave to PayPal 353.5 €

With this hook you can keep this money for you. As if it wasn't enough, the hook can be customized to force the payment gateway depending on customers' country. For example you can use the hook just for specific countries (eg. IT, FR, DE) and/or European Union. Don't worry about multiple currencies. The script automatically handles currency conversion when needed.

Get the Code

Auto-Terminate Free Trials After X Minutes

Free trials for a limited period is a good marketing strategy to capitalize on the leads you get. The problem with trials is that the smallest unit of time for WHMCS is the day meaning that for example you can't provide a trial for VPS that last for a couple of hours. WHMCS can't "think" for a period of less than a full day.

The following action hook allows to automatically terminate or suspend the given products/services after a certain number of minutes. It runs AfterCronJob hook point that normally triggers once every 5 minutes. Visit Setup > Automation Settings and make sure that cron.php runs every 5 minutes as suggested by WHMCS. The hook will do the rest. It also logs performed actions in Activity Log. Here are the variables you need to configure:

  • $productIDs array of Product ID you want to terminate or suspend
  • $terminateAfter terminate or suspend products after the given number of minutes (1440 = full day - 0 to disable) integer
  • $performAction` can choose between Terminate and Suspend

Get the Code

Stronger Password Generator for Auto-Provisioning

We give you not one, not two but three action hooks to override default passwords generated by WHMCS for service provisioning on third-party control panels like Plesk, cPanel, DirectAdmin and custom-made server modules.

  • v1 randomly picks 10 characters from a-zA-Z0-9 and !@#$%^&*()-=+?
  • v2 same as above but makes sure that at least one special character is included in the password
  • v3 for extremely strong passwords. Individually define the number of digits, lowercase, uppercase and special characters to use. The resulting password will not use the same character twice

One-off Products/Services & Domain purchase requires Product/Service

If you have a bit of experience with WHMCS, you know that offering promotions just via coupon codes isn't so flexible.

Many prefer to have products/services created specifically for special deals. Similarly others want to restrict domain purchase to customers with at least a product/service in their accounts. The hook lets you achieve both goals. Simply configure the following variables:

  • kt_onetimeProducts array of product IDs to treat as "one-off" (customer is not allowed to order the same product multiple times)
  • kt_onetimeProductGroups same as above but for product group IDs. Producs inside such groups are treated as one-off
  • kt_firstTimerTollerance product-based restrictions are disabled for new customers placing their first order with you
  • kt_notRepeatable if a customer already has a one-off product, he can't purchase further one-offs (kt_firstTimerTollerance is ignored)
  • kt_domainRequiresProduct domain purchase is allowed only if any of the following conditions is met:
    • Customer has an existing product/service (Pending and Terminated don't count)
    • Customer is purchasing a domain and a product/service
  • kt_onClientRegister ordering one-off products is possible only for clients who registered within the last X number of days (int). Leave false to disable
  • kt_promptRemoval notify customer about restrictions via (previews are below):
    • bootstrap-alert right below Review & Checkout
    • modal on screen
    • js-alert on scren
  • kt_textDisallowed message displayed for product-based restriction
  • kt_textRequireProduct message displayed for domain-based resrticion

When the hook detects that the customer is not allowed to order specific products/services and/or domains, it removes them from WHMCS cart showing alerts.

The script highlights products/services used for promotions in green and with "promo" label.

Get the Code

New Clients as Affiliates

Automatically sets newly registered customers as Affiliates on WHMCS. This way they don't need to join manually.

That said, as you probably already know the affiliate system of WHMCS is very basic. If you need something more complete and sophisticated take a look at Commission Manager.

Get the Code

Send Email & Add Reply on Ticket Status Change

When the status of a support ticket changes, WHMCS doesn't send any notification. We can tweak this process by sending an email and optionally also automatically add a reply to the ticket itself. This way you can guide customers through the resolving process letting them track the progress of tickets.

Get the Code

Ticket Feedback on Auto Close via Escalation Rule

Sending feedback request on ticket closure is a great way to measure customer support satifaction however this feature has a missing piece. A ticket in WHMCS can be set as Closed in three different ways:

  • When the ticket is closed by an admin user
  • For inactivity Setup > Automation Settings > Support Ticket Settings > Close Inactive Tickets
  • Via escalation rules

WHMCS doesn't send any feedback request when the ticket is closed with an escalation rule. The hook in question solves this problem. The only requirements are the following:

  • $cronFrequency must be equal to your System Cron Frequency
  • You must use unique names for escalation rules

Get the Code

Disable Feedback for Unanswered Tickets

WHMCS always sends feedback requests for closed tickets, no matter what. This includes the case of customers closing tickets before you even had the chance to add a reply. For example a customer opens a ticket to report an error on his website. Few minutes later he realizes that it was his fault and closes the ticket. WHMCS still sends feedback request.

This is quite strange as you are asking customers to let you know the «Quality of experience» with your support team. No one has even answered! Some customers could even give you a very bad rating because they feel you're tricking them. Let's patch the hole with this hook.

Get the Code

Client to Group based on Purchased Items

Automatically assign customers to a client group based on purchased product/service, product addon and configurable options. It works only for customers that haven't been assigned to any group yet. Below we're going to show you how to define group/product pairs. Let's take this configuration as example.

$groups['products']['1'] = array('1', '2', '3');
$groups['products']['2'] = array('4');
$groups['productaddons']['1'] = array('2');
$groups['configurableoption']['3'] = array('5' => true, '6' => array('7', '8', '10')); 

They key of the first level of $groups array (eg. ['products']) can assume the following values:

  • products for group/product pairs
  • productaddons for group/product addon pairs
  • configurableoption for group/configurable option paris

The key of the second level of $groups array (['1'], ['2']) represents the client group ID. array() stores product IDs, product addon IDs and configurable options. Let's put it into practice explaining what the above configuration means:

  • Customer A purchases product 1. He goes to client group ID 1
  • Customer B purchases product 2. He still goes to client group ID 1
  • Customer C purchases product 4. He goes to client group ID 2
  • Customer D purchases product 5. No action taken
  • Customer E purchases product 1 and is already assigned to a client group. No action taken
  • Customer F purchases product addon 2. He goes to client group ID 1
  • Customer G purchases a product selecting any value of configurable option ID 5. He goes to client group ID 3
  • Customer H purchases a product selecting specifically 7, 8 or 10 options of configurable option ID 6. He goes to client group ID 3

The script is available in two versions. The configuration is the same. What changes is the hook point:

  • AcceptOrder version assigns the group when the order is accepted - both manually and automatically
  • EmailPreSend version assign the group a moment before WHMCS sends the Welcome Email - any type (eg. Hosting, VPS, CodeGuard, Marketgoo...). This way the group just assigned is immediately ready for use in email templates

Client to Group based on Registration Date

This hook is similar to the one that assigns clients to groups based on purchases. This time we're assigning clients to groups based on registration date or more precisely on user seniority. Let's take this code as example.

$groups['1'] = '90';
$groups['2'] = '180';
$groups['3'] = '365';

The key of $groups array (eg. ['1']) represents the ID of the group while the value user seniority (days between registration date and current date). According to the above configuration, here is what happens:

  • Customer A registered 34 days ago. No change
  • Customer B registered 90 days ago. He goes to client group ID 2
  • Customer C registered 364 days ago. Still group ID 2
  • Customer D registered 500 days ago. He goes to client group ID 3

The hook runs with WHMCS daily cron job meaning that tomorrow the customer C of the above example will move from group 2 to 3. Optionally, you can turn on any of the following features to add some restrictions:

  • $activeCustomers rules apply only on Active customers (boolean true or false)
  • $oldestPurchase rules apply only on if customer has a product/service or domain older than the given number of days (integear)

Get the Code

Client to Group based on Registered Domains

The hook assigns clients to groups based on the number of active domains in their accounts (Active, Grace and Redemption). This is particularly useful for Domain Pricing slabs. Let's take this code as example.

$groups['1'] = '10';
$groups['2'] = '25';
$groups['3'] = '100';

The key of $groups array (eg. ['1']) represents the ID of the group while the value the number of active domains. According to the above configuration, here is what happens:

  • Customer A has 10 domains. He goes to client group ID 2. Next day domains become 9. The the customer is removed from the group
  • Customer B has 99 domains. He still goes to client group ID 2 but will be moved to 3 in case he manages to reach 100 domains
  • Customer C has 250 domains. Group ID 3

The hook runs with WHMCS daily cron job meaning that customers are moved (or removed) from groups on a daily basis. Optionally, you can use the following feature to add some restrictions:

  • $activeCustomers rules apply only on Active customers (boolean true or false)
  • $placeholderGroup used to restrict assignments to a specific group (group ID or false to disable). This option requires further explanation as detailed below

Let's assume we use the following configuration.

$groups['1'] = '10';
$groups['2'] = '25';
$groups['3'] = '100';

$placeholderGroup = '5';

The hook processes assignments only on clients assigned to group ID 5 (the placeholder), 1, 2 and 3. Let's see some examples:

  • Customer A has 250 domains and is assigned to group 5. After cron job he's moved to group 3
  • Customer B has 10 domains and is assigned to group 1 and transfers away one domain. After cron job he's moved to group 5 as now he owns only 9 domains

The placeholder can also be one of the existing group as in the following example:

$groups['1'] = '10';
$groups['2'] = '25';
$groups['3'] = '100';

$placeholderGroup = '1';

In this case the 10 domains requirement for group 1 is ignored. The hook keeps track of changes to clients' group in the Activity Log.

Get the Code

Exempt Existing Clients from Affiliate Commissions

If a visitor places an order for a product or service with the affiliation cookie present, the affiliate earns a commission. The problem is that for WHMCS visitors and customers are the same thing meaning that it gives commissions to affiliates even for orders placed by existing customer.

The hook prevents WHMCS from paying commission for customers registered on your from a given number of days. For example if you set $numberOfDays = '30', WHMCS stops paying commissions for new orders placed by customers registered from more than 30 days on your site.

Get the Code

Prevent changes to Client Custom Fields

WHMCS has an in-built function to lock client profile fields you want to prevent clients being able to edit from clientarea (eg. email, company name). This feature however is not avaiable for client custom fields. Making such fields "disabled" via HTML is not an option. Anyone with bit of knowledge can skip this form of protection.

This hook acts as the last line of defense. It grants that no customer can submit changes. If necessary it can be enabled also for WHMCS Administrators.

If you need something more professional, Billing Extension can bring your WHMCS to the next level with things like monthly invoicing, electronic invoicing, customer retention, Facebook Pixel and much more.

Get the Code

Quote to Invoice conversion without redirect

If you are sending out a lot of quotes on a daily basis, the fact that WHMCS forces a redirect to the newly issued invoice could be frustrating. This hook prevents WHMCS from performing the redirect allowing you to keep woriking on the quote.

Get the Code

Remove/Hide Breadcrumb

WHMCS prepends Portal Home to breadcrumb. There's nothing wrong with that but some people don't like it. This hook removes it from all WHMCS pages.

Bonus tip: if you don't want to use an action hook, you can use the following CSS. The result is the same.

.breadcrumb li:first-child {
.breadcrumb li:nth-child(2):before {
    content:" ";

Get the Code

Knowledgebase Author

WHMCS doesn't store any information about author - the administrator who published a KB article. This hook automatically adds a new column in tblknowledgebase named kt_author (the kt_ prefix is important to avoid naming collision). When an admin adds an article to KB the same hook stores author information and shows it on screen.

Get the Code

Knowledgebase Last Updated Date

WHMCS doesn't store Last Updated date when you edit Knowledgebase articles but you can retreive from Activity Log. It's not a stylish solution but it works. The hook adds lastupdated element to the existing $kbarticle Smarty array so that you can display it in your KB template file.

If you're looking for something more professional and up to date, learn how to benefit from WHMCS SEO using WHMCS as CMS.

Get the Code

Login as Client Language

Every time an administrator uses Login as Client, WHMCS overrides the default language of the selected customer with the one used by the administrator in WHMCS backend. This is bad because you're unknowingly changing the default language for your customer. This also applies for languages that can't be used in clientarea.

Let's say your clientarea is in italian and you're using WHMCS backend in english. When you perform the Login as Client, WHMCS switches customer's language from italian to english and there's no way back. The customer in question is stucked with a language he cannot change. The following hook prevents that to happen.

Get the Code

Prevent emails to be sent based on Client Group

The hook prevents WHMCS from sending General Messages email templats to specific client groups based on a sort of blacklist.

Get the Code

Abort auto-provisioning when there's a Note in the Order

A customer orders a VPS and adds notes to request a particular configuration that requires your manual intervention. In case you're using auto-provisioning, there's no way to stop WHMCS from creating the VPS to let you intervene manually. This hook stops auto-provisioning when there's a note in the order.

Get the Code

Rename Addon Module Label

Let's say you don't like how we named Mercury, Commission Manager, Billing Extension addon modules and you want to change them to CMS, Affiliates and Accounting. Simply change the following hook accordingly. It will work with any WHMCS module.

Get the Code

Add button next to Module's Functions

Here is how you can add a button next to Create, Suspend, Unsuspend (...) functions in product/service view.

Get the Code

Announcements Meta Description

Before you think «Great! I can finally add meta descriptions to WHMCS announcements» wait for a sec and understand the following:

  • WHMCS is terrible at SEO. You need more than this hook to see improvements
  • Meta description is not a ranking factor. It doesn't affect your rankings but CTR

You can use the same approach to implement other meta tags but stay away from meta keywords. It is useless and has been deprecated more than a decade ago by all search engines.

Get the Code

Prevent Indexing on Search Engines

With this hook you can stop search engines from indexing your WHMCS site. This is particularly useful for test installations and for sites you still need to launch. The hook adds noindex meta tag in the <head> of your WHMCS that "tells" search engine crawlers to not index pages.

Get the Code

Promotion Code in Email Template

Invoice Payment Confirmation is an Email Template that WHMCS sends to customers when they pay invoices. By default this message doesn't include any information about promotions. The following hook add coupon code to the invoice recepit (if a promo has been applied).

Once the hook has been added to WHMCS, you can edit Invoice Payment Confirmation email template to customize the look of your message like follows.

{if $assigned_promos}
Promo below:
{foreach from=$assigned_promos item=promo}

Here is a preview of the message.

Get the Code

Promotions array in Email Templates

This hook is capable of including information about existing promotions (aka coupon codes) in any email notifications sent by WHMCS. It adds {$promotions} Smarty array to any of the specified email templates. You only need to iterate records with a Smarty {foreach} as follows.

{if $promotions}
Active Promotions:
	{foreach from=$promotions item=promo}
	<li>{$promo.code} ({if $promo.type == 'Percentage'}{$promo.value}% discount{elseif $promo.type == 'Fixed Amount'}{$promo.value} € discount{elseif $promo.type == 'Price Override'}Price override {$promo.value} €{elseif $promo.type == 'Free Setup'}Free Seutp{/if})</li>

Here's a preview of the following code. Keep in mind that the hook automatically removes expired promotions from the array.

Get the Code

Automatically Accept Order when Invoice is Paid

WHMCS requires administrators to manually accept orders even if automation tasks already took place. The hook automatically accepts orders via API when Invoice is paid.

  • Restrict order acceptance based on $invoiceTotal. The script automatically performs currency conversion. Leave false per auto-accettare tutto
  • Use <= as $operator to auto-accept orders less than or equal to $invoiceTotal. Use >= for the opposite

Get the Code

Cancel Order when an Invoice is beign Cancelled

When an invoice is Mark Cancelled the related order (if exists) is automatically set Cancelled.

Get the Code

Ban Order Expiration

WHMCS administrators can ban IP on the fly directly from order view. The problem with this feature is that WHMCS automatically sets the ban to expire the last day of current year. As you can imagine there's an huge difference between receiving the ban on January instead of December. This hook makes sure that bans always last one full year no matter what.

Get the Code

Hide Google Invisible reCAPTCHA Badge

All it takes to hide Google Invisible reCAPTCHA Badge (bottom-right corner) is a CSS rule. If you don't want to edit your CSS and/or want preserve the change with template updates, use this hook. Before you ask, yes, the correct way to hide the Badge is to use opacity. Using things like display: none and visibility: hidden breaks reCAPTCHA.

Get the Code

Chatstack Disable for Logged-In Users and Administrators

In case you have now idea of what Chatstack is, let me give you a little bit of background. It's an official module of WHMCS that allows to chat with visitors and track their activities. We use it ourselves on our site. It's the little badge at the bottom right corner. Visitors can click it to start chatting with us. In case we're not online, the badge redirects to contact us.

It is worth to mention that in past Chatstack was named LiveHelp. You can purchase it directly from Chatstack or from WHMCS Marketplace. Ignore all the negative reviews. Most of them are from people that have no idea of how to install and configure it.

Let's now move to the hook itself. Once Chatstack is installed on your WHMCS site, it starts tracking everyone including WHMCS administrators and logged-in users. This creates the following problems:

  • You receive notifications about administrators' activities
  • Chatstack doesn't distinguish between visitors and administrators
  • Chat should be reserved for pre-sales but customers can use it for technical support

The hook we made provides two options that allows to:

  • Stop tracking and notifying administrators' activities
  • Prevent logged-in users (existing customers) to use the chat

The only requirement is that you remove any existing integration between WHMCS & Chatstack. The action hook handles everything and supports also WHMCS multi-domain and multi-brand.

Get the Code

Notify Fraudulent Orders

When an order is set as fraud, prior to the change of status actually occurring, the hook sends email notifications to all existing WHMCS administrators (disabled administrators are ignored).

Get the Code

Conditional Support Departments

Restrict the access to support departments based on the products purchased by users. Define rules as follows.

$department['1'] = array('45', '46', '10');
$department['2'] = array('85', '86', '10');
// Keep adding rules one per line

The key of $department array (the [1] and [2] between square brackets) corresponds to the ID of the support department for which we are creating a rule. The value is an array() of product IDs required for access. In a in nutshell, the above configuration unlocks department #1 to users with product IDs 45, 46 and 10. Department #2 requires 85, 86 and 10.

Here are few more things to keep in mind:

  • submitticket.php doesn't show restricted departments
  • Access via direct link submitticket.php?step=2&deptid=2 triggers a redirect to submitticket.php
  • Department dropdown lists only allowed department
  • The same product can be used for multiple rules
  • Pending, Suspended, Terminated, Cancelled and Fraud products are ignored

Get the Code

Abort Email Sending based on User ID and/or Client Group ID

Let's take as example the following configuration:

$disallowedEmailTemplates = array('Invoice Created'); // The name of the email template being sent
$disallowedClientGroups = array('3'); // Client Group ID
$disallowedUserIDs = array('1'); // User ID

We are aborting the sending of Invoice Created email to client ID 1 and also to clients assigned to client group 3. You can specify multiple email templates, client groups and user ID - all these parameters are array(). The $removePDFAttachments can be used to simply remove PDF invoice attachments from emails.

  • $disallowedEmailTemplates the system name of the email template that can be found in Setup > Email Templates. When you edit a template, the system name appears right below Email Templates title
  • $disallowedClientGroups an array of client group IDs that can be found in Setup > Client Groups
  • $disallowedUserIDs an array of user IDs
  • $removePDFAttachments set true if you simply want to remove PDF invoice attachments for the selected users

Get the Code

Generate Missing UUID in tblclients

Importing clients in tblclients table via queries or from phpMyAdmin, does not automatically create uuid values. This script will generate uuid for clients that don't have one yet. It triggers by visiting any page of frontend. Don't forget to remove the it when you finished.

Get the Code

Generate Missing UUID in tblclients

It feels weird when you open Billing > Invoices and WHMCS sorts records by Due Date. A more convenient way to sort invoices is by Invoice Date. It took me plenty of time to figure out how to change default sorting for tables in backend.

WHMCS stores sorting order for each page in the mysterious $_COOKIE['WHMCSSD'] array. Why am I saying mysterious? Because for reasons I can't understand, WHMCS staff decided to json_encode and base64_encode its content. That's why nobody before me knew this secret.

Get the Code

Free Reports Collection

Yay! We didn't stop to action hooks. Below you can find a list of custom WHMCS Reports to give you more in-depth reporting and analytics on the performance of your business. Let's go!

Churn Rate

Rate at which customers stop doing business with you. The report includes charts and graphs to help you interpret the data. For every month of the year you can see:

  • No. of products/domains at the start of the month
  • No. of products/domains at the end of the month
  • Monthly change in the No. of products/domains
  • No. of products/domains acquired during the month
  • No. of products/domains lost during the month
  • Churn rate (percentage)

The reports also shows cumulative statistics (products & domains combined). Churn rate is usually connected to customer retention. The linked article describes how to retain customers. For your information the formula to calculate churn rate is the following.

(Lost products/domains at the end of Time Period / Acquired products/domains at the end of Time Period) * 100

The report doesn't take into account products/services with any of the following billing cycles: One Time, Completed, Free Account. The reason for that is very simple. Such products don't support renewals hence churn rate doesn't apply.

Get the Code

Free Modules Collection

Yep, we also give you some handy modules that can help you with most common operations in WHMCS.

Plesk Checker

Error code: 1013. Error message: Customer with external id 'whmcs_plesk_XX' is not found in panel.

If you're using Plesk I bet you've seen this error at least once in your life. If you try to google it, you'll find a page from Plesk documentation that claims this bug (I quote) «has been already fixed for all versions». I respectfully disagree.

Probably I'll need a week to explain why this error appears. Let's skip this boring part. Fixing the error requires your manual intervention on psa database (Plesk) and more in particular on clients.external_id column as described in the article previously linked.

We created a module that makes this "find and replace" process less frustrating and quicker. Not only it automatically detects all hosting accounts that are returing Error code: 1013 but also additional ones. Here's a preview.

Get the Code

Comments (28)

  1. Rainer Mbongo

    could create a product limiter per account. eg One can only order on free trial

    1. Katamaze | Davide Mantenuto

      You can use this hook to specify products that can be ordered only once per customer.

  2. Jorge Magalhaes

    Could you create a hook that add vat tax to the add funds invoices

    1. Katamaze | Davide Mantenuto

      I'm sorry but this is not possible as such feature is already part of Billing Extension. As we stated on Github, we're open for small and medium-sized projects not in contrast with what we are already selling.

      In any case adding tax to credit is more complex than you think. When you start charging taxes on add funds invoices, you also need to extract VAT every time credit is applied to invoices. If you don't do that customers pay taxes twice: when they add funds and when they apply credit. In order to achieve this goal you need more than an action hook.

  3. Jorge Magalhaes

    Create a new hook that change the client to a new group based on the quantity of the active registered domains in the client account

    1. Katamaze | Davide Mantenuto

      That's a good idea. I opened a feature request on Github this way you can follow it an receive a notification when the hook is ready for use. It will probably take a couple of days.

    2. Katamaze | Davide Mantenuto

      We just finished to create the hook you requested. You can find it here.

    3. Jorge Magalhaes

      Now the only thing i think that lacks in this hook is the possibility to restrict the group change for a specific customer or if the client belongs to a specific group

    4. Katamaze | Davide Mantenuto

      Nice idea. The script has been updated. Now you can set a group that acts as a sort of placeholder

  4. Jonas

    Could you create a hook that shows customers' own IP and location at the top of their client area?

    1. Katamaze | Davide Mantenuto

      I need more details. Are you talking about geolocalizing customers and showing effective IP/location in admin area? If so, what's the purpose?

  5. parsa aminian

    hi LoginAsClientPreserveLanguage.php hook is not working on whmcs 7.10 . could you please test it ?

  6. Javier

    WHMCS 8 get error on Churn_Rate ERROR: Error: Unsupported operand types in Churn_Rate.php:64

    1. Katamaze | Davide Mantenuto

      Thanks for reporting the issue. It was due to changes in Laravel/Capsule that now return a Collection rather than an array. I updated the report so that it works in v8

  7. Jorge Magalhaes

    In the 'Client to Group based on Purchased Items', the hook could work not only when the customer is not associated with any group but on the contrary, it could always work with the exception of if the customer is in a specific group. Another feature that should have, is that if the service is suspended or terminated, the customer's group should be changed to 'none'.

    1. Katamaze | Davide Mantenuto

      It's doable. The hook you are referring to is already pretty much complex so I need some time to understand what to do. Anyway we can continue on Github where you posted a feature request

  8. Jorge Magalhaes

    for the hook 'Client to Group based on Registered Domains' possibly a good feature is that an option with 'on/off' whenever a given customer is changed from group, the domain prices are automatically updated in the customer account. similar to the 'Bulk Auto Recalculate Client Domain Products Services' hook but automatically, whenever a customer is changed from group to group

    1. Katamaze | Davide Mantenuto

      That's a very good point. Could you please submit it as a feature request on Github? This way I can let you know when it's ready and also ask questions (if necessary)

  9. Bill

    Hello thx for the great Hooks.

    I have the following Hook-Request:

    By Default Tlds can be registered for max of 10 Years. But alot of these Tlds have a Discount Price on First Year(New Register) My Registrar do not allow to register this Domains for more then a Year but allow to renewal them for Multiple Years.

    My Question:

    A Hook where i can choose which tlds can be registered for only 1 Year.

    Simply deactivating Years 2-10 in the Pricelist will deactivate the Renewal Option

    1. Katamaze | Davide Mantenuto

      I need to see if this is doable. Please, post this as a feature request on Github so that I can take a look when I have free time.

  10. Pereceh Internet

    can you make a hook like the selector hosting locations ,,, I know that WHMCS can duplicate the product and then adjust it to the Group Server but I think this is very troublesome ...

    1. Katamaze | Davide Mantenuto

      I think there's a way to achieve this goal using a configurable option. Customers can choose the location from this option. When the order is placed, with an action hook I "read" this value and set the correct server ID accordingly before auto-provisioning takes place. That being said, I need to ask you some questions so please submit a feature request on Github so that we continue there.

  11. John

    For the hook 'Client to Group based on Registered Domains', is it possible to make a small change so it only impacts clients with x domains in a specific domain extension, for example .de? Please could you advise on this?

    1. Katamaze | Davide Mantenuto

      That's a good idea. I opened a feature request on Ghithub so that you can follow updates.

  12. Peter

    Thanks for these great hooks. Can we request a hook? We would like to remove affiliate referrals after a set period, like 2 years, so commission stops after this time.

    1. Katamaze | Davide Mantenuto

      That's pretty easy. I opened a feature request on Ghithub so that you can follow updates and receive a notification when the hook is ready for use.

  13. Diego Larsson

    Thank you very much for these excellent hooks

    For a long time I have been looking for a function to be able to hide specific payment gateways from clients from certain countries.

    I will try to explain it, since my native language is not English.

    I currently sell products for Argentina and the rest of the world For Argentina I use the payment gateway "TODOPAGO" so that customers from that country can pay in Argentine pesos For the rest of the world I use the gateway STRIPE To the users of Argentina I show the products in ARS (pesos) and to the rest of the world in USD (dollars) I can achieve this with the Geolocation hook

    When they go to pay the order, both gateways appear, TODOPAGO Argentina and STRIPE, people from Argentina sometimes get confused and select stripe, or vice versa

    I need a hook that HIDE STRIPE to customers in Argentina and hide TODOPAGO to customers in the rest of the world

    Is this possible?

    Thank you very much for your attention, dedication and patience.

    1. Katamaze | Davide Mantenuto

      I am sorry but in my collection there isn't an action hook that can do what you describe but this is perfectly doable. As a reference a couple of years ago I created a module that does exactly this. It allows to set or ban payment methods based on countries.

Speak Your Mind Cancel Reply