---
title: Hooks de front + assets — patron completo
section: examples
slug: front-hook-assets
description: Patron real para registrar CSS/JS, usar hooks de display y pasar variables a Smarty desde modulos PrestaShop, con ejemplos de ecom_stickycart.
keywords: prestashop hooks front assets CSS JS displayHeader actionFrontControllerSetMedia smarty assign modulo
last_updated: 2024-12-01
source_url: "https://ayudaprestashop.es/examples/front-hook-assets"
---

# Hooks de front + assets — patron completo

> Patron real para registrar CSS/JS, usar hooks de display y pasar variables a Smarty desde modulos PrestaShop, con ejemplos de ecom_stickycart.

> **[TIP] Codigo real de produccion**
>
> Patron extraido de multiples modulos reales (ecom_stickycart, ecom_magnificus, ecom_showcombilist). Muestra como combinar hooks de front para añadir funcionalidad visual.

## Registrar CSS y JS

*actionFrontControllerSetMedia — el hook correcto para assets*

```php
<?php

// ══ REGLA: Usar actionFrontControllerSetMedia para CSS/JS ══
// NO usar displayHeader para esto (funciona pero no es correcto)

public function hookActionFrontControllerSetMedia()
{
    // Solo cargar en pagina de producto
    if ($this->context->controller->php_self !== 'product') {
        return;
    }

    // CSS principal del modulo
    $this->context->controller->registerStylesheet(
        'ecom-stickycart-style',
        'modules/' . $this->name . '/views/css/front.css',
        ['media' => 'all', 'priority' => 150]
    );

    // JS principal (defer para no bloquear)
    $this->context->controller->registerJavascript(
        'ecom-stickycart-js',
        'modules/' . $this->name . '/views/js/front.js',
        ['position' => 'bottom', 'priority' => 150, 'attribute' => 'defer']
    );

    // CSS custom del admin (textarea en la config)
    $customCss = Configuration::get('ECOM_STICKY_CUSTOM_CSS');
    if (!empty(trim($customCss))) {
        // Inyectar CSS inline (no como archivo)
        Media::addJsDef([
            'ecomStickyCustomCss' => $customCss,
        ]);
    }

    // Variables PHP → JavaScript
    Media::addJsDef([
        'ecomStickyConfig' => [
            'layout'         => Configuration::get('ECOM_STICKY_LAYOUT'),
            'position'       => Configuration::get('ECOM_STICKY_POSITION'),
            'gap'            => (int) Configuration::get('ECOM_STICKY_GAP'),
            'scrollTrigger'  => (int) Configuration::get('ECOM_STICKY_SCROLL_TRIGGER'),
            'animation'      => Configuration::get('ECOM_STICKY_ANIMATION'),
            'showQty'        => (bool) Configuration::get('ECOM_STICKY_SHOW_QTY'),
            'showStock'      => (bool) Configuration::get('ECOM_STICKY_SHOW_STOCK'),
            'mobileOptimized'=> (bool) Configuration::get('ECOM_STICKY_MOBILE_OPTIMIZED'),
            'enableCartUpdate'=> (bool) Configuration::get('ECOM_STICKY_ENABLE_CART_UPDATE'),
        ],
    ]);
}

// En el JS del modulo estas variables estan disponibles globalmente:
// ecomStickyConfig.layout     → 'classic'
// ecomStickyConfig.position   → 'bottom'
// ecomStickyConfig.showQty    → true
```

## hookDisplayHeader — logica condicional

*Logica condicionada por pagina y configuracion*

```php
<?php

public function hookDisplayHeader()
{
    // Solo en pagina de producto
    if (!($this->context->controller instanceof ProductController)) {
        return '';
    }

    // Comprobar si la categoria actual esta excluida
    $product = $this->context->controller->getProduct();
    if ($product && $this->isCategoryExcluded($product->id_category_default)) {
        return '';
    }

    // Inyectar CSS dinamico via style tag
    $bgColor  = Configuration::get('ECOM_STICKY_BG_COLOR');
    $txtColor = Configuration::get('ECOM_STICKY_TXT_COLOR');
    $btnColor = Configuration::get('ECOM_STICKY_BTN_COLOR');

    return '<style>
    :root {
        --sticky-bg: ' . htmlspecialchars($bgColor) . ';
        --sticky-text: ' . htmlspecialchars($txtColor) . ';
        --sticky-btn: ' . htmlspecialchars($btnColor) . ';
    }
    </style>';
}

private function isCategoryExcluded(int $idCategory): bool
{
    $excluded = Configuration::get('ECOM_STICKY_EXCLUDE_CATEGORIES');
    if (empty($excluded)) {
        return false;
    }
    $excludedIds = array_map('intval', explode(',', $excluded));
    return in_array($idCategory, $excludedIds);
}
```

## hookDisplayFooter — renderizar template

*Inyectar HTML via template Smarty*

```php
<?php

public function hookDisplayFooter()
{
    // Solo en pagina de producto
    if ($this->context->controller->php_self !== 'product') {
        return '';
    }

    // Obtener datos del producto actual
    $product = $this->context->controller->getProduct();
    if (!$product) {
        return '';
    }

    // Preparar datos para el template
    $this->context->smarty->assign([
        'sticky_product_name'  => $product->name,
        'sticky_product_price' => Tools::displayPrice(
            $product->getPrice(true)
        ),
        'sticky_product_image' => $this->context->link->getImageLink(
            $product->link_rewrite,
            $product->getCover($product->id)['id_image'] ?? 0,
            'small_default'
        ),
        'sticky_in_stock'      => StockAvailable::getQuantityAvailableByProduct(
            $product->id
        ) > 0,
        'sticky_layout'        => Configuration::get('ECOM_STICKY_LAYOUT'),
        'sticky_position'      => Configuration::get('ECOM_STICKY_POSITION'),
    ]);

    return $this->display(__FILE__, 'views/templates/hook/sticky-bar.tpl');
}

// ── Template: views/templates/hook/sticky-bar.tpl ──
// <div id="ecom-sticky-cart"
//      class="sticky-cart sticky-cart--{$sticky_layout}"
//      data-position="{$sticky_position}">
//   <img src="{$sticky_product_image}" alt="{$sticky_product_name}">
//   <span class="sticky-cart__name">{$sticky_product_name}</span>
//   <span class="sticky-cart__price">{$sticky_product_price}</span>
//   {if $sticky_in_stock}
//     <button class="sticky-cart__btn">{l s='Add to cart' mod='ecom_stickycart'}</button>
//   {/if}
// </div>
```

## Patron completo integrado

| Hook | Funcion | Cuando usarlo |
| --- | --- | --- |
| actionFrontControllerSetMedia | registerStylesheet/JS + Media::addJsDef | SIEMPRE para CSS y JS de front |
| displayHeader | CSS variables, meta tags, logica condicional | CSS dinamico, inline styles |
| displayFooter | HTML via template Smarty | Elementos visuales que van al final del body |
| displayProductAdditionalInfo | Info extra en ficha producto | Badges, avisos, datos extra |
| displayProductButtons | Botones junto a 'Añadir al carrito' | Wishlist, comparar, compartir |
| hookDisplayBackOfficeHeader | Assets solo en el admin | CSS/JS para controllers admin |

> **[I] Orden de ejecucion de hooks**
>
> actionFrontControllerSetMedia → displayHeader (en <head>) → [body content] → displayFooter (antes de </body>). Los assets registrados con registerStylesheet/JS se incluyen automaticamente en las posiciones correctas.


---

*Fuente: [https://ayudaprestashop.es/examples/front-hook-assets](https://ayudaprestashop.es/examples/front-hook-assets). Version Markdown generada automaticamente para consumo por LLMs.*
