{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Extending Further","description":"Developer documentation for the WHMCS API — the","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"extending-further","__idx":0},"children":["Extending Further"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"custom-functions","__idx":1},"children":["Custom Functions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Custom functions allow you to define extra operations that can be performed using the module. The custom functions can perform actions, or define extra client area pages/output. Permissions can be granted for who can use each custom function, be it just clients, just admins, or both."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The convention for custom function names follow the same as any other function of a module. It must begin with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["yourmodulename_"]},", and then the custom function name."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The easiest way to show this is with an example. So let's take an example of a Push Function that will use a template, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["pushdomain.tpl"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"function yourmodulename_push($params) {\n\n    $domainid = $params['domainid'];\n    $sld = $params['sld'];\n    $tld = $params['tld'];\n\n    return array(\n        'templatefile' => 'pushdomain',\n        'breadcrumb' => array(\n            'clientarea.php?action=domaindetails&domainid='.$domainid.'&modop=custom&a=push' => 'Push Domain',\n        ),\n        'vars' => array(\n            'var1' => 'valuehere',\n            'var2' => 'anothervaluehere',\n        ),\n    );\n}\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The above shows how to define custom functions, use the parameters passed, and return an array response. The response can either be a simple empty array/error for an action function, or a complex array return like the above to define an extra client area page for extra domain management functionality."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Now we need to allow clients to use this. The following function defines that clients are allowed to invoke the push function, and will add a menu option to the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Domain Actions"]}," dropdown within the client area for it."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"function yourmodulename_ClientAreaCustomButtonArray() {\n    return array(\n        \"Push Domain\" => \"push\",\n    );\n}\n"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The key value of the array is what is displayed to admins/clients on the button or menu options for the commands, and the value is the custom function name excluding the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["modulename_"]}," prefix."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you want to provide clients with a custom button or way to invoke a function, then this can be done as follows within a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".tpl"]}," file described in the previous Client Area Output section:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"<form method=\"post\" action=\"clientarea.php?action=domaindetails\">\n<input type=\"hidden\" name=\"domainid\" value=\"{$domainid}\" />\n<input type=\"hidden\" name=\"modop\" value=\"custom\" />\n<input type=\"hidden\" name=\"a\" value=\"reboot\" />\n<input type=\"submit\" value=\"Reboot VPS Server\" />\n</form>\n"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"idn-domains","__idx":2},"children":["IDN Domains"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you wish to support registration and management of IDN domain names via a registrar module, the domain object can be"," ","used to access various parameters related to the domain. A domain name is considered IDN if it contains at least one character that is in a language-specific script or alphabet. IDN is supported for second level domain names but not top level at this time."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following options are available:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"$domainObj = $params['original']['domainObj'];\n$fullDomainUnicode = $domainObj->toPunycode(); // The full domain name as stored in the database.\n$isIdn = $domainObj->isIdn(); // Returns true if domain is an IDN domain.\n$fullDomainPunycode = $domainObj->toUnicode(); // The full domain name in Unicode.\n$secondLevelUnicode = $domainObj->getUnicodeSecondLevel(); // The domain name (excluding TLD) in Unicode.\n$secondLevelPunycode = $domainObj->getPunycodeSecondLevel(); // The domain name (excluding TLD) converted to Punycode.\n$tld = $domainObj->getTopLevel(); // The Top Level Domain for the given domain.\n"},"children":[]}]},"headings":[{"value":"Extending Further","id":"extending-further","depth":1},{"value":"Custom Functions","id":"custom-functions","depth":2},{"value":"IDN Domains","id":"idn-domains","depth":2}],"frontmatter":{"title":"Extending Further","seo":{"title":"Extending Further"}},"lastModified":"2026-08-03T17:00:42.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/domain-registrars/extending-further","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}