Hooks in PrestaShop Themes

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.


Understanding Hooks

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.

Use Hooks Instead of Hardcoded Modules

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.

🚨 Hardcoded Module Template

{* 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>

✅ Using Hooks Correctly

{* In the header.tpl file *}
{hook h='displayBanner'}

💡 Why?

Allows merchants to rearrange module positions inside a hook via the back office.

Maintains modular architecture, keeping themes compatible with future updates.

Native Hooks and Custom Hooks

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.

✅ Registering a Custom Hook in 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

✅ Calling the Hook in a Template

{hook h='displayCustomBanner'}

💡 Why use custom hooks?

Keeps themes flexible without modifying core theme files.

Allows custom modules to attach to new location in your theme.

Avoid Displaying Empty Hooks

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:

🚨 Displaying Potentially Empty Hooks

<div class="container">
  {hook h='displayBanner'}
</div>

✅ Testing Hook Output Before Displaying It

{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}

💡 Why?

✔ Prevents empty <div> or other empty tags in the DOM.

✔ Ensures hooks are only displayed when needed.

Avoid Calling Hooks Multiple Times

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.

🚨 Duplicate Hook Call

<div class="header">
  {hook h='displayBanner'}
</div>

<div class="footer">
  {hook h='displayBanner'}
</div>

✅ Use Capture to Render Template Only Once

{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}

💡 Why?

Prevents unnecessary duplicate HTML output.

Optimizes page load time and performance if you really need to call a hook twice.

Using Widgets When Hooks Don’t Fit Your Needs

If hooks don’t fit your need, consider using {widget} instead. Widgets provide a more flexible way for modules to inject content dynamically.

✅ Use Widgets for More Flexibility

{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}

💡 Why?

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.

Conclusion

Using hooks correctly in a PrestaShop theme ensures clean, modular, and future-proof theme development.

🚀 Key Takeaways:

✔ 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.