Panel Support Screen Hooks
The twenty-one placement points of the support screens: the ticket detail, the reply form, the list rows and the department forms.
Overview
The placement points of the support screens live here: every part of the ticket detail, the list rows and the department forms.
A few points on the ticket detail hand you a privilege flag. It is not a gate: the core disables its own buttons with it, but it does not stop your output. If you show something that needs the privilege, do the check yourself.
Reference
A badge or button in the ticket title
Appears in the title row of the ticket detail. It suits a case number in another system or a shortcut of your own.
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.Hook::add('ui:admin.tickets_detail.header_actions', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The top of the side column
Appears in the side column of the ticket detail, above the first card.
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.Hook::add('ui:admin.ticket_detail.sidebar_top', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Adding an operation to the side column
Appears among the operation boxes in the side column. It puts a ticket operation of your own beside the built-in ones.
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.Hook::add('ui:admin.ticket_detail.sidebar_actions', 10, function ($ticket, $opPriv) {
// Yetki bilgisi kapi DEGIL: kendiniz sinayin.
if (!$opPriv) return null;
return '<div class="operation-box"><button onclick="acmeEscalate('
. (int) ($ticket['id'] ?? 0) . ')">Acme</button></div>';
});A row on the ticket details card
Appears among the fields of the ticket details card. Add metadata of your own beside the core fields.
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.Hook::add('ui:admin.ticket_detail.details_card.meta', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Above the conversation
Appears immediately above the reply thread. It suits context or a warning from another system.
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.Hook::add('ui:admin.ticket_detail.conversation.before', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The top of the reply form
Appears above the box staff write their reply in. It suits a warning that should be seen before writing.
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.Hook::add('ui:admin.ticket_detail.reply_form.top', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The reply form toolbar
Appears in the toolbar of the reply form. Put your own insert or template button here.
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.Hook::add('ui:admin.ticket_detail.reply_form.toolbar', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Below the reply editor
Appears immediately below the text editor. It suits an extra option or a confirmation box before sending.
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.Hook::add('ui:admin.ticket_detail.reply_editor.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Below the canned replies
Appears below the canned reply options. The place to add a template source of your own.
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.Hook::add('ui:admin.ticket_detail.canned_replies.after', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The bottom of the internal note form
Appears below the internal note box. Notes are never shown to the customer.
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.Hook::add('ui:admin.ticket_detail.note_form.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});A new tab on the ticket detail
Runs once the tabs of the ticket detail are built. You do not return HTML: you add the tab through the object’s method.
Hook::add('ui:admin.ticket_detail.tabs', 10, function ($tab, $ticket) {
$tab->add('acme', 'Acme', Acme::renderTab((int) ($ticket['id'] ?? 0)));
});The very bottom of the ticket page
Appears at the very end of the page.
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.Hook::add('ui:admin.tickets_detail.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});A badge on a list row
Appears on every row of the ticket list. It puts a status badge of your own beside the core ones.
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.Hook::add('ui:admin.tickets_list.row_badges', 10, function ($model) {
// SATIR BASINA calisir: burada sorgu yapmayin, onceden toplayin.
if (!Acme::isEscalated((int) ($model['id'] ?? 0))) return null;
return '<span class="badge bg-danger">Acme</span>';
});The ticket list toolbar
Appears in the button group above the ticket list.
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.Hook::add('ui:admin.tickets_list.toolbar', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Above the table on the ticket list
Appears immediately above the ticket table.
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.Hook::add('ui:admin.tickets_list.before_table', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});The department list toolbar
Appears in the toolbar of the department list.
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.Hook::add('ui:admin.department_list.toolbar', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Above the table on the department list
Appears immediately above the department table.
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.Hook::add('ui:admin.department_list.before_table', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Above the ticket creation form
Appears above the form staff use to open a ticket for a customer.
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.Hook::add('ui:admin.tickets_edit.before_content', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Below the ticket creation form
Appears below the same form, at the bottom of the page.
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.Hook::add('ui:admin.tickets_edit.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Above the department form
Appears above the department add and edit form.
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.Hook::add('ui:admin.department_edit.before_content', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Below the department form
Appears below the same form.
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.Hook::add('ui:admin.department_edit.bottom', 10, function () {
return '<div class="alert alert-info">Acme</div>';
});Pitfalls
The privilege parameter on the ticket detail tells you whether the viewer holds it; it does not block your output on its own. If you would rather not show an operation button to somebody without the privilege, put the condition in your own listener. The real check stays in the operation on the server: hiding here is only visibility.
The list badge point is called separately for every ticket on the page. A listener doing a database query or an outside call inside it produces fifty queries on a fifty-row page and slows the list noticeably. Collect what you need once and read it from memory.
Related Articles
- Support Ticket Hooks
- Ticket View Hooks
- Management Panel Hooks
Thanks for your feedback!
Our support team is here around the clock for anything you can't find above.