Jump to content
Sign in to follow this  

Hook to block subdomains from being used as existing domains

Recommended Posts

When it comes time to order a hosting plan, sometimes you don't want your users to be able to enter in a subdomain when using an existing domain for their order.

In this post I am going to walk you through a basic hook that prevents entering a subdomain by using some client-side JavaScript.

Our first order of business will be to check out the WHMCS hooks index to see if there is a hook point that will fit our needs: https://developers.whmcs.com/hooks/hook-index/

It turns out, the ClientAreaFooterOutput hook will do nicely: https://developers.whmcs.com/hooks-reference/output/#clientareafooteroutput

The reason for this is because that hook point will allow you to inject HTML code, which also can contain JavaScript, into the client-side template so you can make the magic happen.

Before getting into more detail, let's go ahead and dive right into the code. You can also download it from this link block_subdomains.txt (then rename the extension to .php). Here is the entire snippet:

add_hook('ClientAreaFooterOutput', 1, function($vars) {
    $jqueryCode = '<script>
    $("#owndomainsld").on("keyup", function(e) {
        var str = $("#owndomainsld").val();
        if ( str.indexOf(".") != -1 ) {
            alert("Subdomains are not allowed!");
    if (strpos($_SERVER['REQUEST_URI'], 'cart.php') !== false ) {
        return $jqueryCode;

The first thing to notice is the add_hook function is being called with the ClientAreaFooterOutput hook point as the first argument and an anonymous function as the second argument. The anonymous function also has a $vars variable being passed into it. For this example the $vars variable is not actually being used in the body of the function, but it does contain some useful parameters should you need to access them. Those parameters can be found in the documentation for the hook point linked above.

The next thing to notice is the $jqueryCode variable. which is actually a PHP string that contains the JavaScript code we will be injecting into our client-side page. Since WHMCS uses the jQuery JavaScript library and loads it on the page, we can use it in our code.

First, we need to bind an event listener to the keyup event on the domain text box and provide it a callback function to execute when that event occurs. This can be easily done by targeting the element's HTML ID attribute. That is what is happening here:

$("#owndomainsld").on("keyup", function(e) {...

After that, the value of the domain text field is stored in a JavaScript variable called str. Since this code is inside our callback function, it will be executed every time the user presses a key on the keyboard and then releases it:

var str = $("#owndomainsld").val();

Once we have that text stored in our str variable, we need to check it for a dot or period '.' character to see if it is a subdomain.

This can be done with indexOf string function in JavaScript. If the text appears to be a subdomain, we'll go ahead and empty out the text field and then show an alert to the user to let them know that subdomains are not allowed:

if ( str.indexOf(".") != -1 ) {
    alert("Subdomains are not allowed!");

Finally, the last part of the hook does a case-insensitive string search on the $_SERVER['REQUEST_URI'] (the URL of the page you're visiting), to check and see if a cart page is being rendered. If a cart page is detected, the JavaScript code is injected into that page so it can run.

if (strpos($_SERVER['REQUEST_URI'], 'cart.php') !== false ) {
    return $jqueryCode;

Putting it all together, we get the final results in WHMCS which look like the picture here:

subdomain not allowed.png

I hope this post proved helpful and gives some insight on some of the ways that WHMCS can be extended to do many different things outside the box! 

At the time of writing this post, this hook was tested on the latest stable release of WHMCS 7.4.2 and should work with any that fall under Active Support as per the LTS schedule here: https://docs.whmcs.com/Long_Term_Support#WHMCS_Version_.26_LTS_Schedule

If you have any feedback, questions, or concerns that I did not cover in this post, please feel free to reach out!

Share this post

Link to post
Share on other sites

I didn't tried your script, but it seems to block also full legit third-level domains: i.e., .co.uk ...

I guess the only way to be sure if it's a sub-domain or if it's a legit third-level would be a whois query...


Share this post

Link to post
Share on other sites

Hello Remitur,

I can confirm that this hook does not block the use of TLDs such as .co.uk because the hook only affects the SLD field on the shopping cart.

The TLD field will remain unaffected and allow the user to proceed through the checkout process.

I have attached a couple screenshots to show how this looked on my test installation.

co uk domain test.png


Share this post

Link to post
Share on other sites
This topic is now closed to further replies.
Sign in to follow this  

  • Similar Content

    • By JesusSuarz
      I'm trying to get some way to query if a user is online.
      I don't want to know the current user.
      if not something you can define for example $clientid or $userid or $emailclient ...
      I am making an external site. and i need to work with user sessions. (I am making a remote connection with the api).
      this function does not currently exist in the api available.
      I've been seeing this: https://developers.whmcs.com/advanced/authentication/
      however I do not see that it allows to define the user.
      I was also seeing this: https://docs.whmcs.com/Sessions
      I was able to save the cookie in the database, however I can't find any way to identify the one that belongs to each user.
      any idea how I can get (which users are online?) ..
      (please nothing to do with smarty, only php).

      postdata: forget to tell the method I use to get user authentication in my application.
      create the following code for my application:
      I first make a connection to the api: https://developers.whmcs.com/api/authentication/
      soon ValidateLogin: https://developers.whmcs.com/api-reference/validatelogin/
      soon GetClientsDetails: https://developers.whmcs.com/api-reference/getclientsdetails/
      soon CreateSsoToken: https://developers.whmcs.com/api-reference/createssotoken/
      // validar usuario $command = 'ValidateLogin'; $postData = array( 'email' => $email_user, //post 'password2' => $password_user, //post ); $api_login = localAPI($command, $postData); //var de id de usuario: $api_login["userid"]; // si se encuentra el user entonces traer detalles del usuario via email $clientid = array(); // array que tiene el id del cliente if ($api_login["userid"] == true) { $command = 'GetClientsDetails'; $postData = array( 'email' => $email_user, // email login ); $details_client = localAPI($command, $postData); $clientid[] = $details_client["client_id"]; } // variable del clientid es: $clientid[0]; // crear token de session $command = 'CreateSsoToken'; $postData = array( 'client_id' => $clientid[0], ); $results_ssotoken = localAPI($command, $postData); echo '<pre>'; var_dump($results_ssotoken); echo '</pre>'; this will create the url with (CreateSsoToken) where the user will be redirected for autologin, however the cookie is created only after entering the client area. that's why I don't know how to get the cookie, or identify the user.
      @brian! would you help me with this?
    • By Mas-J
      Dear All,
      I want to show the Next Invoice Date under Next Due Date when admin access Page Client Details on Product/Services Tab.
      But, I've no idea how to show it, I just know to get the Next Invoice Date value related from tblhosting
      Anyone can help me to show it ? Thank you.
      <?php use WHMCS\Database\Capsule; add_hook('AdminClientServicesTabFields', 1, function($vars) { $PID = $vars['id']; $nextinvoicedate = Capsule::table('tblhosting')->where('id', $PID)->pluck('nextinvoicedate'); $result = array(); $result['nextinvoicedate'] = $nextinvoicedate; return $result });

    • By ramf
      I'm newbie and I'm trying to modify a  CSS file so it will work with the new twenty-one template.
      One of the things I want to do is to change the direction of the  buttons in the card-headers so instead of like this:

      It will be like this:

      The only way I found to do it is by changing the  class of the div  for each one of them  from "float-right" to  "float-left".
      I tried doing it with javascript - something like  that:
      document.querySelectorAll("div .card-header h3.card-title.m-0 .float-right")[0].classList.add("float-left"); document.querySelectorAll("div .card-header h3.card-title.m-0 .float-right")[0].classList.remove("float-right"); Is this the best way to achieve my goal?
      with the above scenario I have to add the code for each one of the  card-headers . I tried doing it with this function:
      var cardHeaderLength = document.querySelectorAll("div .card-header h3.card-title.m-0 .float-right").length; var cardHeader =document.querySelectorAll("div .card-header h3.card-title.m-0 .float-right"); for (var i = 0; i < cardHeaderLength; i++) { cardHeader[i].classList.add("float-left"); cardHeader[i].classList.remove("float-right"); }; So my questions are: is there a better way to change the float direction without javascript or something like that?
    • By Nelson Neoh
      Hi all,
      I wish to perform some registrar API activities in the registrar hooks, but as the hook's vars or params didn't provide credential details, I tried to get direct from DB Capsule and unfortunately noticed the data stored in encrypted format...
      Any suggestions to over come this?
      Best Regards,
    • By Trescpress
      I am working on a custom hook and I find that just by adding an input field of type Tel, the country code is added by WHMCS.
      I am basically showing a modal from my hook if a condition is met.
      Now I am testing the example code on the IntlTelInput plugin website (https://intl-tel-input.com/node_modules/intl-tel-input/examples/gen/default-country-ip.html)
      $(document).ready(function(){ var input = document.querySelector("#phone"); window.intlTelInput(input, { initialCountry: "auto", geoIpLookup: function(callback) { $.get("https://ipinfo.io", function() {}, "jsonp").always(function(resp) { var countryCode = (resp && resp.country) ? resp.country : "us"; callback(countryCode); }); }, }); }); <input type="tel" id="phone">  
      But that's returning an error:
      I basically want to sow the local country code in the form. is there a way to achieve this? bearing in mind that I am not in the tpl file, just echoing a modal from my hook.
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated