# Panel Customer Screen Hooks

https://dev.wisecp.com/es/admin-client-screen-hooks

The nineteen placement points of the customer screens: summary cards, tabs, the list toolbar and the creation form.

## Overview

The placement points of the customer screens live here. They all work the same way. The HTML you return appears at that point. Return `null` when you have nothing to add.

Two points fall outside that pattern. **Adding a tab** receives an object rather than HTML, and the addition happens through a method call. The **document field form** is collected once as the page opens and then fixed. It cannot vary with the field being edited.

## Reference

### The top of the summary tab

uiadmin.client_detail.summary.top

`admin/users/detail` above the cards

Appears at the very top of the customer summary, above the statistic cards. The right place for a risk banner, a last-contact note or a key-account warning.

Parameters 3

$userarrayThe full customer record.

$user_idintThe customer id.

$user_statsarrayThe counters worked out: active and inactive services, invoices, tickets.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.summary.top', 10,
    function ($user, $user_id, $user_stats) {
        $score = Acme::riskScore($user_id);
        if ($score < 70) return null;   // eklenecek bir sey yoksa null

        return '<div class="alert alert-warning">Risk skoru: ' . (int) $score . '</div>';
    });
```

### Adding a row to the information card

uiadmin.client_detail.summary.info_card

`admin/users/detail` a row inside the card

Appears after the last row of the information card. The place for a field such as an outside customer number, the referral source or an account manager.

Parameters 3

$userarrayThe full customer record.

$client_infoarrayThe extra detail pairs of the customer.

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.summary.info_card', 10,
    function ($user, $client_info, $user_id) {
        $crm = Acme::crmId($user_id);
        if ($crm === '') return null;

        // Cikti kacissiz basilir: dis degeri kendiniz temizleyin.
        return '<div class="row"><div class="col-5">CRM</div><div class="col-7">'
             . htmlspecialchars($crm) . '</div></div>';
    });
```

### Adding an operation to the actions card

uiadmin.client_detail.summary.action_cards

`admin/users/detail` an operation box

Appears after the last operation in the actions card. It puts an operation of your own beside the built-in ones.

Parameters 2

$userarrayThe full customer record.

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.summary.action_cards', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The bottom of the summary tab

uiadmin.client_detail.summary.bottom

`admin/users/detail` below the cards

Appears once the cards of the summary tab end. The place for a card or an information panel of your own.

Parameters 2

$userarrayThe full customer record.

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.summary.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### A badge or button in the title area

uiadmin.client_detail.header_actions

`admin/users/detail` beside the badges

Appears at the end of the status badges in the page title. Put a badge of your own or a shortcut button here.

Parameters 3

$userarrayThe full customer record.

$user_idintThe customer id.

$client_infoarrayThe resolved customer details: kind, tax status and protection flags.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.header_actions', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### A new tab on the customer detail

uiadmin.client_detail.tabs

`admin/users/detail` an object, not an array

Runs once every core tab is built. Unlike the other placement points you **do not return HTML** here: you add the tab through the object’s method.

Parameters 3

$tabobjectThe tab object; add a new tab through its method.

$userarrayThe full customer record.

$user_idintThe customer id.

Return 1

voidThe return is **not used**. This point shows no HTML: the change happens by calling the object’s method. A listener returning HTML quietly does nothing here.

Listener PHP

```php
Hook::add('ui:admin.client_detail.tabs', 10, function ($tab, $user, $user_id) {
    // HTML DONDURMEYIN: sekme nesneye eklenir.
    $tab->add('acme', 'Acme', Acme::renderTab($user_id));
});
```

### The bottom of the profile tab

uiadmin.client_detail.profile.bottom

`admin/users/detail` below the profile

Appears once the vertical tabs of the profile are on screen. It suits a verification summary or an extra preference section.

Parameters 3

$userarrayThe full customer record.

$client_infoarrayThe extra details of the customer.

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.profile.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the contacts tab

uiadmin.client_detail.contacts.top

`admin/users/detail` top of the tab

Appears above the address and contact list. It suits an address verification state or a warning about a missing billing address.

Parameters 3

$userarrayThe full customer record.

$user_idintThe customer id.

$user_addressesarrayThe address and contact records of the customer.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.contacts.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the sub-users tab

uiadmin.client_detail.subusers.top

`admin/users/detail` top of the tab

Appears above the sub-user list. It suits a warning about unaccepted invitations or a note on permission policy.

Parameters 2

$userarrayThe full customer record.

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.subusers.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the invoices tab

uiadmin.client_detail.invoices.top

`admin/users/detail` top of the tab

Appears above the invoice table. It suits an outstanding balance warning or the state of automatic payment.

Parameters 1

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.invoices.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the services tab

uiadmin.client_detail.orders.top

`admin/users/detail` top of the tab

Appears above the service and order list. It suits a renewal warning or a provisioning failure banner.

Parameters 1

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.orders.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the support tab

uiadmin.client_detail.tickets.top

`admin/users/detail` top of the tab

Appears above the ticket table. It suits a count of open tickets or a satisfaction summary.

Parameters 1

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.tickets.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the notes tab

uiadmin.client_detail.notes.top

`admin/users/detail` top of the tab

Appears above the note list. The place to show system notes coming from an outside source.

Parameters 2

$user_idintThe customer id.

$notesarrayThe notes of the customer.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.notes.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The very bottom of the customer page

uiadmin.client_detail.bottom

`admin/users/detail` end of the page

Appears at the very end of the page, immediately before the footer. It suits a panel that belongs to no tab.

Parameters 2

$userarrayThe full customer record.

$user_idintThe customer id.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_detail.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The customer list toolbar

uiadmin.client_list.toolbar

`admin/users` no parameters

Appears in the button group above the list. Add a button for an export or a bulk action of your own.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_list.toolbar', 10, function () {
    return '<a href="/acme/export" class="btn btn-outline-secondary">'
         . '<i class="bi bi-download"></i> Acme</a>';
});
```

### Above the table on the customer list

uiadmin.client_list.before_table

`admin/users` above the table

Appears after the statistic card and the filter panel, immediately above the table.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_list.before_table', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the customer creation form

uiadmin.client_create.before_content

`admin/users` above the form

Appears above the new customer form. It suits an information banner or an extra instruction.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_create.before_content', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Below the customer creation form

uiadmin.client_create.bottom

`admin/users` below the form

Appears once the new customer form ends, at the bottom of the page.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe **HTML you return appears**. With several listeners the outputs are appended one after another in priority order. Empty text, `null` and `false` are skipped, so return `null` when you have nothing to add. The output enters the page unescaped — clean anything coming from outside yourself.

Listener PHP

```php
Hook::add('ui:admin.client_create.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### An extra section on the document field form

uiadmin.document_field.form

`admin/users` collected once

Puts an extra section into the add and edit window of the document verification fields. If you introduced a field type of your own, ask for its settings here.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe HTML you return appears. ? Because the window is built in the browser, the output is collected **once as the page opens** and embedded as a constant: it **cannot vary** with the field being edited. If you need per-field behaviour, show all of it and choose in your own code.

Listener PHP

```php
Hook::add('ui:admin.document_field.form', 10, function () {
    // The output is collected once: it cannot vary per field.
    return '<div class="mb-3"><label>Acme check</label>'
         . '<input class="form-control" name="acme_rule"></div>';
});
```

## Pitfalls

> **The output enters the page unescaped**
> 
> Whatever you return at these points enters the page as it stands. Embedding a value from outside (a customer name, a response from another system, form input) directly creates a **code execution hole in the panel**. Escape the value yourself.

> **The tab point takes no HTML**
> 
> The tab point looks like the others but **shows no HTML**: it hands you an object and the tab is added through its method. A listener returning HTML quietly does nothing here, and raises no error either, which makes it hard to spot.

## Related Articles

- [Panel Screen Data Hooks](https://dev.wisecp.com/en/admin-screen-data-hooks)
- [Customer Account Hooks](https://dev.wisecp.com/en/customer-account-hooks)
- [Management Panel Hooks](https://dev.wisecp.com/en/hooks-in-the-management-panel)
