# Panel Shell and Order Hooks

https://dev.wisecp.com/es/admin-shell-and-order-hooks

The twenty placement points of the panel shell, the dashboard and the order screens: the head, the body, the top menus and the order detail.

## Overview

Two different scales meet here. The **shell points** run on every page of the panel: the head, the body and the top menus. The **dashboard and order points** belong to a single screen.

The difference is cost. A heavy file placed at a shell point slows the whole panel; a point tied to one screen concerns only that screen.

## Reference

### Adding a style to the panel

uiadmin.head.css

`admin/inc` on every page

Appears in the head section of the panel, on every page. Link a stylesheet of your own here.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe HTML you return enters the head section. ? It runs on **every page of the panel**: a heavy stylesheet here slows the whole panel down. If you need it on one screen, use a point on that screen instead.

Listener PHP

```php
Hook::add('ui:admin.head.css', 10, function () {
    // It runs on EVERY page: keep it light.
    return '<link rel="stylesheet" href="' . Acme::assetUrl('panel.css') . '">';
});
```

### Adding a script to the panel

uiadmin.head.js

`admin/inc` on every page

Appears in the panel footer, on every page. Despite its name the output sits at the **end of the page**, where scripts load.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe HTML you return appears at the end of the page. ? It runs on every page of the panel. If your script throws, **the panel’s own scripts can stop too**: wrap your code in your own error handling.

Listener PHP

```php
Hook::add('ui:admin.head.js', 10, function () {
    // A failure here can stop the panel's own scripts too.
    return '<script src="' . Acme::assetUrl('panel.js') . '" defer></script>';
});
```

### The start of the body

uiadmin.body.begin

`admin/inc` on every page

Appears at the very start of the page body, on every page. It suits an announcement banner across the whole panel.

Parameters 0

—It takes no parameters.

Return 1

string|nullThe HTML you return appears at the start of the body. It runs on every page; use your own container so the layout holds.

Listener PHP

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

### The end of the body

uiadmin.body.end

`admin/inc` on every page

Appears at the very end of the page body. It is the right place for modals and hidden containers.

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.body.end', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### An item in the create menu

uiadmin.header.create_menu

`admin/inc` the top menu

Appears in the create menu on the top bar. Put a quick-create link of your own here.

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.header.create_menu', 10, function () {
    return '<li><a class="dropdown-item" href="/acme/new">Acme record</a></li>';
});
```

### An item in the help menu

uiadmin.header.help_menu

`admin/inc` the top menu

Appears in the help menu on the top bar. It suits a link to your own documentation or support.

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.header.help_menu', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the dashboard

uiadmin.dashboard.top

`admin/index` top of the board

Appears at the very top of the dashboard, above the statistic cards.

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.dashboard.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### After the statistic cards

uiadmin.dashboard.statistics.after

`admin/index` after the cards

Appears immediately after the statistic cards on the dashboard. The place to add a counter card of your own to the row.

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.dashboard.statistics.after', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The bottom of the dashboard

uiadmin.dashboard.bottom

`admin/index` end of the board

Appears at the very end of the dashboard. The place to add a panel 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.dashboard.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### A badge or button in the order title

uiadmin.order_detail.header_actions

`admin/orders/detail` the title area

Appears in the title row of the order detail.

Parameters 3

$orderarrayThe order record on screen.

$order_idintThe order id.

$order_statusstringThe order status: waiting, in process, active or cancelled.

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.order_detail.header_actions', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the order detail

uiadmin.order_detail.top

`admin/orders/detail` above the content

Appears above the order content. The place to show a warning that depends on the status.

Parameters 3

$orderarrayThe order record on screen.

$order_idintThe order id.

$order_statusstringThe order status: waiting, in process, active or cancelled.

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.order_detail.top', 10,
    function ($order, $order_id, $order_status) {
        if ($order_status !== 'waiting') return null;

        return '<div class="alert alert-info">Acme onayi bekleniyor</div>';
    });
```

### Adding an operation to the order items

uiadmin.order_detail.item_actions

`admin/orders/detail` two flags arrive

Appears in the operation area of the order items. Two flags beside you say which operation makes sense.

Parameters 3

$orderarrayThe full order record.

$has_pending_itemsboolWhether any service or add-on is still waiting. A false means nothing is left to provision.

$has_moduleboolWhether the order holds a service on a module. A false leaves a button acting on a remote server with nothing to do.

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.order_detail.item_actions', 10,
    function ($order, $has_pending_items, $has_module) {
        // Modulsuz siparişte uzak islem butonu bosa calisir.
        if (!$has_pending_items || !$has_module) return null;

        return '<button class="btn btn-sm" onclick="acmeProvision()">Acme</button>';
    });
```

### The very bottom of the order page

uiadmin.order_detail.bottom

`admin/orders/detail` end of the page

Appears at the very end of the page.

Parameters 3

$orderarrayThe order record on screen.

$order_idintThe order id.

$order_statusstringThe order status: waiting, in process, active or cancelled.

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.order_detail.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The order list toolbar

uiadmin.order_list.toolbar

`admin/orders` no parameters

Appears in the toolbar of the order list.

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.order_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the table on the order list

uiadmin.order_list.before_table

`admin/orders` no parameters

Appears immediately above the order 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.order_list.before_table', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Above the order creation form

uiadmin.order_create.before_content

`admin/orders` no parameters

Appears above the manual order form.

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.order_create.before_content', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### Below the order creation form

uiadmin.order_create.bottom

`admin/orders` no parameters

Appears below the same form.

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.order_create.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The top of the domain pricing screen

uiadmin.domain_pricing.top

`admin/domains` no parameters

Appears above the extension price 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.domain_pricing.top', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The bottom of the domain pricing screen

uiadmin.domain_pricing.bottom

`admin/domains` no parameters

Appears below the extension price 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.domain_pricing.bottom', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

### The document list toolbar

uiadmin.domain_doc_list.toolbar

`admin/domains` no parameters

Appears in the toolbar of the extension document requirement list.

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.domain_doc_list.toolbar', 10, function () {
    return '<div class="alert alert-info">Acme</div>';
});
```

## Pitfalls

> **Shell points run on every page of the panel**
> 
> The style and script points are not limited to one screen: whatever page an administrator opens, your output goes into it. A heavy file, or a script calling an outside service on every load, slows **the whole panel**. If what you add belongs to one screen, use that screen’s own point.

> **A failure in your script can stop the panel’s scripts**
> 
> Code you add at the end of the page runs beside the panel’s own. An uncaught error halts script execution in the browser: what goes unresponsive is not your panel but **the screen the administrator is using**. Wrap your code in your own error handling.

## Related Articles

- [Management Panel Hooks](https://dev.wisecp.com/en/hooks-in-the-management-panel)
- Order Hooks
- [Panel Analytics Hooks](https://dev.wisecp.com/en/admin-analytics-hooks)
