Hook List

The module system provides two types of hooks: event hooks (PHP callbacks) and display hooks (Smarty template injection points). Catalog source: Module::HOOKS, getHookCatalog(), and getDisplayHookCatalog() in core/Module.php.

Event hooks run PHP code at specific moments (e.g. when an order is placed).
Display hooks render HTML into store / admin templates via {$hooks.*} or {$adminHooks.*}.

Event Hooks

Register listeners inside your module's boot() method using Module::registerHook(). Only hooks listed in Module::HOOKS are accepted.

Hook Name When It Fires Arguments
smarty.assign During Module::bootstrap() — after all enabled modules are loaded $smarty instance
head.assets When front-end CSS/JS assets are collected via Module::getHeadAssets() &$assets array with css and js keys
footer.html Legacy footer HTML injection (prefer display hooks instead) —
admin.menu Admin sidebar menu is built (registerAdminMenuLink or registerHook) &$items menu items array
order.placed After a new order is successfully created (checkout / POS) Order data array
order.updated When an order is updated (admin / API / status change) $order, previous status / context extras
product.updated When a product is saved (admin, Web API, quick stock, bulk tools) $idProduct, $product, $isNew
cart.changed After the cart contents change (add / update / remove) Cart summary array from Cart::getSummary()
form.captcha.validate Form submit CAPTCHA check (Captcha::validate()) $form name, &$error string
product.filter.sql Before catalog product SQL runs — modules can alter SQL / params &$sql, &$params, filter context array
catalog.filter.context Reserved catalog filter context hook (registered in HOOKS) Context payload (when fired by callers)

Display Hooks (Front)

Assigned per module in admin and stored in module_display_hooks. Output is available in Smarty as {$hooks.hook_name} (dotted names nest, e.g. {$hooks.head.top}).

Hook Name Location Smarty Variable
footer Store footer {$hooks.footer}
header Top bar / header {$hooks.header}
main_menu Main category menu {$hooks.main_menu}
mobile_menu Mobile drawer menu {$hooks.mobile_menu}
head.top Inside <head> (top) {$hooks.head.top}
home Home page body {$hooks.home}
home_slider Home page top slider {$hooks.home_slider}
home_promo_slider Home promo / campaign slider {$hooks.home_promo_slider}
home_bottom Home page bottom section {$hooks.home_bottom}
catalog_filters Category / catalog filters {$hooks.catalog_filters}
product Product listing context (needs id_product) {$hooks.product}
product_detail Product detail page {$hooks.product_detail}
product_tab Product tab button {$hooks.product_tab}
product_tab_content Product tab content panel {$hooks.product_tab_content}
product_inf Product detail info block {$hooks.product_inf}
order_payment Checkout payment step {$hooks.order_payment}
order_confirmation Order confirmation page {$hooks.order_confirmation}
auth_social Login / register — social buttons {$hooks.auth_social}
contact_form Contact form — CAPTCHA / extra fields {$hooks.contact_form}
auth_login Login form — CAPTCHA {$hooks.auth_login}
auth_register Register form — CAPTCHA {$hooks.auth_register}

Display Hooks (Admin)

Admin hooks use {$adminHooks.*} (via Module::renderAdminHooks()). Implement renderAdminDisplayHook() in your module for hooks starting with admin_.

Hook Name Location Smarty Variable
admin_login Admin login form — CAPTCHA {$adminHooks.admin_login}
admin_product_button Product edit — next to Save {$adminHooks.admin_product_button}
admin_order_detail Admin order detail {$adminHooks.admin_order_detail}
admin_header Admin content top (all pages) {$adminHooks.admin_header}
admin_footer Admin footer (all pages) {$adminHooks.admin_footer}
admin_dashboard_top Dashboard — top {$adminHooks.admin_dashboard_top}
admin_dashboard_kpi Dashboard — below KPI cards {$adminHooks.admin_dashboard_kpi}
admin_dashboard_main_left Dashboard — left column {$adminHooks.admin_dashboard_main_left}
admin_dashboard_main_right Dashboard — right column {$adminHooks.admin_dashboard_main_right}
admin_dashboard_bottom Dashboard — page bottom {$adminHooks.admin_dashboard_bottom}
Deferred hooks (rendered lazily via Module::refreshHook($smarty, $hookName, $context) or admin render): product, product_tab, product_tab_content, product_inf, order_payment, order_confirmation, auth_social, admin_product_button, admin_order_detail, admin_header, admin_footer, and all admin_dashboard_* hooks.

Declaring Display Hooks in Your Module

In your module class, define which display hooks are supported and which are enabled by default on install:

  • $displayHooks — hook name => description (shown in admin)
  • $defaultDisplayHooks — hooks auto-assigned on install()
  • renderDisplayHook($hook, $context) — front HTML
  • renderAdminDisplayHook($hook, $context) — admin HTML for admin_* hooks

Assigning Hooks via Admin

Hook assignments are saved with Module::setDisplayHooks($moduleName, $hookNames). Only hooks listed in both $displayHooks and the global display hook catalog are accepted.

PHP
<?php

// ── Event hooks in boot() ───────────────────────────────────────
public function boot(): void
{
    Module::registerHook('order.placed', function (array $order): void {
        Logger::info('Order placed: ' . ($order['id_order'] ?? ''));
    });

    Module::registerHook('order.updated', function (array $order, $oldStatus = null): void {
        // status / cargo / content edits
    });

    Module::registerHook('product.updated', function (int $idProduct, $product = null, $isNew = false): void {
        // sync external catalog, clear caches, etc.
    });

    Module::registerHook('cart.changed', function (array $cart): void {
        // abandoned-cart tracking, analytics
    });

    Module::registerHook('form.captcha.validate', function (string $form, string &$error): void {
        // set $error when CAPTCHA fails
    });

    Module::registerHook('smarty.assign', function ($smarty): void {
        if ($smarty) {
            $smarty->assign('myModuleEnabled', true);
        }
    });

    Module::registerHook('head.assets', function (array &$assets): void {
        $assets['css'][] = 'https://cdn.example.com/extra.css';
    });
}

// ── Display hooks: declare + render ────────────────────────────
public array $displayHooks = [
    'footer'         => 'Footer block',
    'product_detail' => 'Product detail section',
    'auth_login'     => 'Login CAPTCHA',
];

public array $defaultDisplayHooks = ['footer'];

public function renderDisplayHook(string $hook, array $context = []): ?string
{
    return match ($hook) {
        'footer' => $this->renderFrontTemplate('footer', [
            'message' => Settings::get('MY_MODULE_TEXT'),
        ]),
        'product_detail' => $this->renderFrontTemplate('product_detail', [
            'id_product' => $context['id_product'] ?? 0,
        ]),
        default => null,
    };
}
footer.tpl (Display Hook Example)
{* assets/templates/front/footer.tpl *}

<div class="my-module-footer">
    {if $message}
        <p>{$message|escape}</p>
    {/if}
</div>
Refresh a deferred hook on product page
<?php

// Call from product detail controller after $smarty is ready:
Module::refreshHook($smarty, 'product_detail', [
    'id_product' => (int) $product['id_product'],
]);

// Smarty template:
// {$hooks.product_detail}
Admin display hook example
<?php

public array $displayHooks = [
    'admin_order_detail' => 'Extra block on order detail',
    'admin_dashboard_top' => 'Dashboard banner',
];

public function renderAdminDisplayHook(string $hook, array $context = []): ?string
{
    return match ($hook) {
        'admin_order_detail' => $this->renderAdminTemplate('order-detail', $context),
        'admin_dashboard_top' => $this->renderAdminTemplate('dashboard-top', $context),
        default => null,
    };
}
Register display hooks in module class
<?php

// Minimum setup inside {name}.php:

public array $displayHooks = [
    'footer' => 'Shown in store footer',
];

public array $defaultDisplayHooks = ['footer'];

public function renderDisplayHook(string $hook, array $context = []): ?string
{
    if ($hook !== 'footer') {
        return null;
    }

    return $this->renderFrontTemplate('footer', $context);
}