Hooks are essential for extending and customizing PrestaShop themes and modules in a clean and maintainable way. They allow dynamic content injection without modifying core files, ensuring modularity and compatibility across themes and modules.
Hooks in PrestaShop allow modules to inject content into predefined locations inside a theme or other modules, enabling a modular and extensible structure.
Types of Hooks in PrestaShop:
👀 Display Hooks → Use to render content → Example: displayHeader
, displayHome
, displayFooter
.
⚙️ Action Hooks → Use to execute logic → Example: actionFrontControllerSetMedia
, actionProductAdd
.
A theme should not write a module template logic or directly include a module’s template inside core .tpl
files. Instead, always use hooks to maintain flexibility and compatibility.
{* In the header.tpl file *}
{include file="modules/ps_banner/ps_banner.tpl"}
{* OR *}
<div id="ps_banner">
template related to ps_banner module
</div>
{* In the header.tpl file *}
{hook h='displayBanner'}
✔ Allows merchants to rearrange module positions inside a hook via the back office.
✔ Maintains modular architecture, keeping themes compatible with future updates.
PrestaShop provides many native display hooks. A well-designed theme should implement all the display{Something}
Front Office native hooks to ensure compatibility with third-party modules. However, themes can also define custom hooks if necessary.
config/theme.yml
global_settings:
hooks:
custom_hooks:
- name: displayCustomBanner
title: "Custom Banner Hook"
description: "Used to display a promotional banner in the header."
modules_to_hook:
displayCustomBanner:
- ps_banner
{hook h='displayCustomBanner'}
✔ Keeps themes flexible without modifying core theme files.
✔ Allows custom modules to attach to new location in your theme.
A hook may not return any content if no module is attached to it. In this case, displaying the hook along with its surrounding HTML structure is unnecessary and can result in useless HTML code in the theme.
To prevent this, use Smarty {capture}
to check if the hook has content before rendering it, including its surrounding HTML structure:
<div class="container">
{hook h='displayBanner'}
</div>
{capture name="banner"}{hook h='displayBanner'}{/capture}
{* you can use `trim` to avoid false positives *}
{block name='header_banner'}
{if !empty($smarty.capture.banner|trim)}
<div class="container">
{$smarty.capture.banner nofilter}
</div>
{/if}
{/block}
✔ Prevents empty <div>
or other empty tags in the DOM.
✔ Ensures hooks are only displayed when needed.
Be careful not to call the same hook multiple times, as it can cause unnecessary duplicate content and performance issues. However, if you really need to call a hook more than once, use {capture}
to optimize it.
<div class="header">
{hook h='displayBanner'}
</div>
<div class="footer">
{hook h='displayBanner'}
</div>
{capture name="banner"}{hook h='displayBanner'}{/capture}
{block name='header_banner'}
{if !empty($smarty.capture.banner)}
<div class="header">
{$smarty.capture.banner nofilter}
</div>
{/if}
{/block}
{block name='footer_banner'}
{if !empty($smarty.capture.banner)}
<div class="footer">
{$smarty.capture.banner nofilter}
</div>
{/if}
{/block}
✔ Prevents unnecessary duplicate HTML output.
✔ Optimizes page load time and performance if you really need to call a hook twice.
If hooks don’t fit your need, consider using {widget}
instead. Widgets provide a more flexible way for modules to inject content dynamically.
{capture name="ps_banner"}{widget name="ps_banner"}{/capture}
{if !empty($smarty.capture.ps_banner)}
<div class="header">
{$smarty.capture.ps_banner nofilter}
</div>
{/if}
✔ Ensures the module content and its surrounding HTML structure are displayed only when needed.
✔ Can give more flexibility to the theme developer.
✔ Use widgets when you need finer control over module placement.
Using hooks correctly in a PrestaShop theme ensures clean, modular, and future-proof theme development.
✔ Always use a hook or widget instead of hardcoded module-related templates.
✔ Check hook content {capture}
before displaying it to avoid empty HTML structure.
✔ Use theme.yml
to register new hooks when needed.
✔ Avoid duplicate hook calls to optimize performance.