{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Widgets","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":"widgets","__idx":0},"children":["Widgets"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Widgets are the building blocks of the WHMCS Admin Dashboard."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Widgets are pluggable and can be created as part of a custom module."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Widgets that ship with WHMCS by default can be found in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/modules/widgets/"]}," directory. They are shipped unencoded to allow for expansion and customisation."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"widget-sample","__idx":1},"children":["Widget Sample"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following code sample demonstrates how to create a custom widget using a hook file."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"<?php\n\n/**\n * Standard add_hook call @see https://developers.whmcs.com/hooks/getting-started/\n */\nadd_hook('AdminHomeWidgets', 1, function() {\n    /**\n     * Return a new instance of the widget object for display\n     */\n    return new SampleWidget();\n});\n\n/**\n * Sample Widget example\n */\nclass SampleWidget extends \\WHMCS\\Module\\AbstractWidget\n{\n    /**\n     * @type string The title of the widget\n     */\n    protected $title = 'Hello World';\n\n    /**\n     * @type string A description/purpose of the widget\n     */\n    protected $description = '';\n\n    /**\n     * @type int The sort weighting that determines the output position on the page\n     */\n    protected $weight = 150;\n\n    /**\n     * @type int The number of columns the widget should span (1, 2 or 3)\n     */\n    protected $columns = 1;\n\n    /**\n     * @type bool Set true to enable data caching\n     */\n    protected $cache = false;\n\n    /**\n     * @type int The length of time to cache data for (in seconds)\n     */\n    protected $cacheExpiry = 120;\n\n    /**\n     * @type string The access control permission required to view this widget. Leave blank for no permission.\n     * @see Permissions section below.\n     */\n    protected $requiredPermission = '';\n\n    /**\n     * Get Data.\n     *\n     * Obtain data required to render the widget.\n     *\n     * We recommend executing queries and API calls within this function to enable\n     * you to take advantage of the built-in caching functionality for improved performance.\n     *\n     * When caching is enabled, this method will be called when the cache is due for\n     * a refresh or when the user invokes it.\n     *\n     * @return array\n     */\n    public function getData()\n    {\n        $clients = localAPI('getclients', []);\n\n        return array(\n            'welcome' => 'Hello World!',\n            'clients' => $clients['clients'],\n        );\n    }\n\n    /**\n     * Generate Output.\n     *\n     * Generate and return the body output for the widget.\n     *\n     * @param array $data The data returned by the getData method.\n     *\n     * @return string\n     */\n    public function generateOutput($data)\n    {\n        $clientOutput = [];\n        foreach ($data['clients']['client'] as $client) {\n            $clientOutput[] = \"<a href=\\\"clientsprofile.php?id={$client['id']}\\\">{$client['firstname']} {$client['lastname']}</a>\";\n        }\n\n        if (count($clientOutput) == 0) {\n            $clientOutput[] = 'No Clients Found';\n        }\n\n        $clientOutput = implode('<br>', $clientOutput);\n\n        return <<<EOF\n<div class=\"widget-content-padded\">\n    <div>{$data['welcome']}</div>\n    <div id=\"sampleWidgetClientOutput\">{$clientOutput}</div>\n</div>\nEOF;\n    }\n}\n\n\n"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"widget-sample-output","__idx":2},"children":["Widget Sample Output"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Using the sample code, the widget will output will look something like:"]},{"$$mdtype":"Tag","name":"img","attributes":{"src":"/assets/sample-widget-output.6b9217c1c3e372158c8109dd8a1ddc26e552b1f5560f8d0bf59549cd76b9bc0a.29962483.png","alt":"Widget Output Sample"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"naming-convention","__idx":3},"children":["Naming Convention"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The widget filename and folder should be in the same format as PHP class names due to how WHMCS imports the files from the respective folder."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following file naming conventions are acceptable formats:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"PascalCase or StudlyCaps\ncamelCase\nsnake_case\n"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"permissions","__idx":4},"children":["Permissions"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Widgets use the administrator role access control permissions system."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The permission you define for a widget must match one of the access control permissions defined in WHMCS."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The most commonly used permissions are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["List Clients"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["View Clients Summary"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Perform Server Operations"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Perform Registrar Operations"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Add New Order"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Create Invoice"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["List Support Tickets"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Configure General Settings"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a full list of permissions, see \\WHMCS\\User\\Admin\\Permission::all();"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"abstractwidget","__idx":5},"children":["AbstractWidget"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["More information on the AbstractWidget class used in the sample can be found at http://docs.whmcs.com/classes/7.1/WHMCS/Module/AbstractWidget.html"]}]},"headings":[{"value":"Widgets","id":"widgets","depth":1},{"value":"Widget Sample","id":"widget-sample","depth":2},{"value":"Widget Sample Output","id":"widget-sample-output","depth":3},{"value":"Naming Convention","id":"naming-convention","depth":3},{"value":"Permissions","id":"permissions","depth":2},{"value":"AbstractWidget","id":"abstractwidget","depth":2}],"frontmatter":{"title":"Widgets","seo":{"title":"Widgets"}},"lastModified":"2026-08-03T17:00:42.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/advanced/widgets","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}