Odoo How-To

How to Create a Custom Snippet in Odoo Website

Step-by-step guide to building reusable drag-and-drop building blocks for the Odoo Website editor — from XML template to live snippet panel. Verified for Odoo 18 & 19.

iWesabe Editorial TeamJuly 6, 20227 min read

Odoo Website's drag-and-drop editor is built on reusable building blocks called snippets. Every block you see in the editor panel — from hero banners to testimonial carousels — is a snippet registered via an XML view that inherits from the main snippet list. Creating your own snippet follows the same pattern: write an HTML template, register it in the editor panel, and optionally attach CSS and JavaScript options. This guide covers the complete workflow for Odoo 18 and 19.

What Is an Odoo Snippet?

A snippet (also called a building block) is a self-contained HTML section that website editors can drag from the panel onto any page. Snippets consist of three parts: an HTML template (the visual block), a snippet registration view (which makes it appear in the editor panel), and optional snippet options (JavaScript classes that add editor controls like colour pickers or layout toggles).

Snippet component overview
ComponentFile locationRequiredPurpose
HTML templateviews/snippets/s_my_snippet.xmlYesThe visual block dropped onto the page
Registration viewviews/snippets/snippets.xmlYesAdds the block to the editor panel under a category
Snippet options JSstatic/src/js/options.jsNoEditor controls (layout, colour, visibility toggles)
CSS stylesstatic/src/scss/s_my_snippet.scssNoScoped styles for the snippet block
__manifest__.py entryModule rootYesDeclares XML + JS + CSS assets to Odoo's asset pipeline

Module Structure

Custom snippets must live inside an Odoo module. If you are adding a snippet to an existing website module, skip the scaffold step. For a new module, the minimum directory layout is:

text
my_website_snippets/
├── __init__.py
├── __manifest__.py
├── static/
│   └── src/
│       ├── js/
│       │   └── options.js          # snippet options (optional)
│       └── scss/
│           └── s_my_snippet.scss   # snippet styles (optional)
└── views/
    └── snippets/
        ├── s_my_snippet.xml        # HTML template
        └── snippets.xml            # editor panel registration

Step 1 — Write the HTML Template

xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
  <template id="s_my_cta_banner" name="My CTA Banner">
    <section class="s_my_cta_banner" data-snippet="s_my_cta_banner"
             data-name="My CTA Banner">
      <div class="container text-center py-5">
        <h2 class="s_my_cta_banner_title">Your headline goes here</h2>
        <p class="lead s_my_cta_banner_subtitle">
          Supporting text for your call to action.
        </p>
        <a href="#" class="btn btn-primary btn-lg">Get Started</a>
      </div>
    </section>
  </template>
</odoo>

Key points: the root element must be ``. The `data-snippet` attribute must match the template `id`. The `data-name` attribute sets the tooltip shown in the editor when the user hovers over the dropped block.

Step 2 — Register the Snippet in the Editor Panel

The editor panel is controlled by the view `website.snippets`. You extend it using an XPath to inject your snippet thumbnail into one of the panel categories: Content, Structure, Inner Content, or Features.

Editor panel categories and their XPath targets
CategoryXPath targetTypical use
Content//div[@id="snippet_content"]Hero banners, text blocks, media
Structure//div[@id="snippet_structure"]Columns, cards, layouts
Features//div[@id="snippet_feature"]Counters, tabs, accordions
Inner Content//div[@id="snippet_innerContent"]Elements placed inside other snippets
xml
<?xml version="1.0" encoding="utf-8"?>
<odoo>
  <!-- Register snippet in the "Content" panel category -->
  <template id="snippets" inherit_id="website.snippets">
    <xpath expr="//div[@id='snippet_content']" position="before">
      <t t-snippet="my_website_snippets.s_my_cta_banner"
         t-thumbnail="/my_website_snippets/static/src/img/thumb_my_cta_banner.png"/>
    </xpath>
  </template>
</odoo>

Step 3 — Declare Files in __manifest__.py

python
{
    'name': 'My Website Snippets',
    'version': '1.0',
    'category': 'Website',
    'depends': ['website'],
    'data': [
        'views/snippets/s_my_snippet.xml',
        'views/snippets/snippets.xml',
    ],
    'assets': {
        'web.assets_frontend': [
            'my_website_snippets/static/src/scss/s_my_snippet.scss',
            'my_website_snippets/static/src/js/options.js',
        ],
    },
    'installable': True,
}

Step 4 — Add Snippet Options (Optional)

Snippet options are JavaScript classes that extend `SnippetOptionWidget` (or one of its sub-classes). They add editor panel controls — colour pickers, layout toggles, text inputs — that appear when the user clicks your snippet in the editor. Options are bound to the snippet's root CSS selector.

javascript
/** @odoo-module **/
import options from "@web_editor/js/editor/snippets.options";

options.registry.MyCTABanner = options.Class.extend({
    // Called when the user changes an option value
    setBannerStyle: function (previewMode, value) {
        this.$target.toggleClass("s_my_cta_banner_dark", value === "dark");
        this.$target.toggleClass("s_my_cta_banner_light", value === "light");
    },
});

The registry key (`MyCTABanner`) must match the `data-js` attribute you add to your registration `` element, or Odoo uses the CSS class name of the snippet's root element as a fallback key.

Step 5 — Install the Module and Test

  1. Restart the Odoo server to pick up the new module: `./odoo-bin -c odoo.conf -u my_website_snippets`.
  2. Open the Website app and click **Edit** on any page.
  3. In the building blocks panel, locate your snippet under the category you registered it in (e.g. Content).
  4. Drag the snippet onto the page and confirm it renders correctly.
  5. Click the dropped block to open the editor panel and verify any custom options appear.
  6. Save the page and reload in normal (non-edit) mode to confirm the snippet displays without editor scripts.

Troubleshooting — Common Issues

Snippet troubleshooting reference
SymptomLikely causeFix
Snippet not visible in editor panelXML not declared in __manifest__.py `data` list, or module not updatedAdd the XML file to `data`, then run `-u my_module`. Clear browser cache.
Snippet appears but renders blankTemplate ID mismatch between s_my_snippet.xml and the `t-snippet` referenceVerify `t-snippet='module_name.template_id'` matches exactly, including the module prefix.
CSS styles not appliedSCSS file not in `web.assets_frontend` or Odoo assets not re-generatedAdd SCSS path to manifest assets, restart server with `-u`, clear cache with `?debug=assets`.
Snippet options panel empty / JS not runningOptions JS not bundled in the correct asset (must be in `web.assets_backend` for editor mode)Add options.js to both `web.assets_frontend` and `web.assets_backend` in manifest.
`data-snippet` warning in browser console`data-snippet` value does not match the template ID on the root `<section>`Set `data-snippet='s_my_cta_banner'` on the root tag to match the template `id` exactly.

Version Notes

Snippet behaviour across Odoo versions
Odoo versionKey change affecting snippets
Odoo 15Legacy asset bundle: `website.assets_frontend`. Editor options use `options.Class.extend()`.
Odoo 16Asset bundle renamed to `web.assets_frontend`. OWL 2 introduced — but snippet options still use legacy JS class system.
Odoo 17`@odoo-module` ESM syntax required for new JS files. `data-snippet` attribute enforced — console warning if missing.
Odoo 18Snippet panel UI redesigned — category order may differ. `t-thumbnail` path convention unchanged. Options JS API stable.
Odoo 19No breaking changes to snippet registration or options API. `web.assets_frontend` bundle remains canonical.

Need Custom Website Building Blocks for Your Odoo Site?

Our Odoo-certified developers build custom snippets, website themes, and full e-commerce integrations tailored to Saudi business requirements.

WhatsApp

Frequently Asked Questions

What is the difference between a snippet and a widget in Odoo Website?
A snippet (building block) is a self-contained HTML section dragged from the editor panel onto a page by a website editor — no coding required after creation. A widget is a Python/JavaScript UI component used in Odoo backend forms and views. Snippets are front-end only and designed for non-technical content editors.
Can I add a custom snippet without creating a new Odoo module?
Not reliably. Snippets require XML views and potentially JavaScript/CSS assets, which must be declared in a module's `__manifest__.py` to survive upgrades. Adding them directly via the Odoo backend technical menu (`ir.ui.view`) is possible for testing but the changes will be overwritten on module updates. Always place production snippets inside a proper module.
How do I make a snippet available only on specific pages?
Use the `groups` attribute on the `` registration element to restrict by user group, or use a `t-if` condition that evaluates context. For page-type filtering (e.g. only on blog posts), add a `data-snippet-type` attribute and handle it in a snippet option's `isShown()` method to hide the block from the panel when the page type does not match.
My snippet was saved on a page but disappeared after a module update. Why?
If the template XML was modified or removed during an update, Odoo may neutralise saved snippet instances that reference the old template. Always version-control your snippet templates and avoid renaming or deleting template IDs in production. If you need to restructure a snippet, create a new template ID and keep the old one as an alias until all page instances are migrated.
Can I use Odoo Studio to create a snippet?
Odoo Studio does not currently support creating website snippets. Studio is designed for backend views (form, list, kanban), fields, and report customisation. Custom website snippets require module development as described in this guide.
How do I make snippet text editable by website editors?
Add the class `o_editable` to any element whose text content should be editable directly in the Website editor. For inline elements (headings, paragraphs, links), this is sufficient. For structured content like images or buttons, use the appropriate Odoo editor attributes (`data-original-src`, `data-bs-target`) that the editor recognises for richer controls.
iWesabe Editorial Team

iWesabe Editorial Team

Practitioner insights on Odoo ERP, ZATCA compliance, and Saudi enterprise digital operations — written by iWesabe's consulting, finance, and engineering teams.

About iWesabe

Related Articles