Panel Screen Data Hooks
The thirteen hooks over what the customer, service and tool screens show.
Overview
The hooks that change what panel screens show live here: the customer detail and list, the service management cards, add-on buttons, critical notifications and the theme version lookup.
Two differ from the rest: the profile tabs and the security accordion hand you a component object rather than an array, and you add through a method call.
Reference
Changing the customer extra details
Runs once the extra detail fields on a customer page are read.
Hook::add('filter:admin.client_detail.info', 10, function (&$client_info, $user_id) {
$client_info['acme_tier'] = Acme::tierOf($user_id);
});Adding a sub-tab to a customer profile
Runs while the vertical tabs of a customer profile are built. Add a tab of your own here.
Hook::add('filter:admin.client_detail.profile_subtabs', 10,
function (&$profileTab, $user, $user_id) {
// An object, not an array: call its method.
$profileTab->add('acme', 'Acme', Acme::renderPanel($user_id));
});Adding a section to the security area
Runs while the security settings accordion of a customer is built.
Hook::add('filter:admin.client_detail.security_accordion', 10,
function (&$secAccordion, $client_info, $user_id) {
$secAccordion->add('acme-sessions', 'Acme sessions', Acme::sessions($user_id));
});Changing the customer statistics
Runs once the counters on a customer page are worked out.
Hook::add('filter:admin.client_detail.statistics', 10, function (&$user_stats, $user_id) {
$user_stats['acme_open_cases'] = Acme::openCases($user_id);
});Changing the customer list filters
Runs once the filter criteria of the customer list are built.
Hook::add('filter:admin.client_list.filters', 10, function (&$dynamic_filter) {
// A new key must be handled in the listing query too.
$dynamic_filter['acme_tier'] = Acme::tierFilterValue();
});Changing the service management cards
Runs once the management cards on a service detail are prepared. Add a card of your own, hide one, or change the order.
cards holds the card content and layout says which card sits in which column and in what order. ? Update both: a card missing from the layout never appears, and a layout key with no card is quietly skipped.Hook::add('filter:admin.service_detail.management_cards', 10, function (&$context) {
// Update BOTH: the card and the layout.
$context['cards']['acme'] = Acme::renderCard($context['service'] ?? []);
$context['layout']['right'][] = 'acme';
});Changing the add-on settings buttons
Runs once the buttons on an add-on settings page are prepared.
Hook::add('filter:admin.addon_configure.buttons', 10, function (&$buttons) {
// Emptying it entirely leaves no buttons at all.
$buttons['acme-sync'] = [
'text' => 'Sync Acme',
'class' => 'btn btn-outline-primary',
'icon' => 'bi bi-arrow-repeat',
'onclick' => 'acmeSync()',
];
});Changing the address of an uploaded image
Runs after the address of an image uploaded into the editor is produced. This is how you move images onto a delivery network.
Hook::add('filter:admin.editor_upload_url', 10, function (&$url, $file_path) {
$url = Acme::pushToCdn($file_path) ?: $url;
});Following an image upload
Runs after an image is uploaded into the editor.
Hook::add('action:admin.editor_image_uploaded', 10, function ($file_path, $url) {
// The address is the one AFTER the filter ran.
Acme::noteAsset($file_path, $url);
});Adding to the critical notification list
Runs once the critical notification list in the panel header is prepared.
Hook::add('filter:admin.notifications.critical', 10, function (&$critical_transaction_notifications) {
// Fill every field the template expects.
foreach (Acme::criticalAlerts() as $a) $critical_transaction_notifications[] = $a;
});Following a panel notification
Runs when a system notification lands in the panel.
Hook::add('action:admin.notified', 10, function ($name, $data, $level, $event_id) {
// Zero means nothing was written.
if ($level === 'error' && $event_id) Acme::page($name, $data);
});Taking over the theme version lookup
Runs before a theme is asked about a new version. Return an answer and no remote call is made.
Hook::add('filter:admin.theme_version_check', 10, function ($key, $manifest) {
// A filled return means NO remote call is made.
if (!str_starts_with($key, 'Acme')) return null;
return Acme::versionJson($key);
});Adjusting the theme version response
Runs after the version response arrives and before it is decoded. Its sibling picks the source; this hook adjusts what came back.
Hook::add('filter:admin.theme_version_response', 10, function (&$key, &$manifest) {
// Both parameters are consumed: changing them has no effect.
Acme::noteVersionCheck($key);
});Pitfalls
In the service management cards the content sits in one list and the layout in another. Add only the content and the card never appears; write only a name into the layout and that name is quietly skipped. Update both.
The profile sub-tabs and the security accordion hand you a component object. A listener treating it like an array fails; you add through the object’s own method.
Related Articles
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.