Building Dynamic Website Snippets with OWL in Odoo 18
By Braincuber Team
Published on February 11, 2026
Static HTML snippets are useful, but modern websites crave interactivity. Enter OWL (Odoo Web Library). With Odoo 18, you can seamlessly embed powerful, reactive Javascript components directly into the website builder as drag-and-drop snippets.
In this guide, we will build a "New Arrivals Ticker" snippet. Unlike standard snippets, this one will fetch the latest products from the database in real-time, render them using a client-side OWL component, and display them in a responsive card layout—all without reloading the page.
Why Use OWL for Snippets?
- Reactivity: The UI updates instantly when data changes.
- Performance: Fetch only the data you need via JSON RPC, reducing server load.
- Modularity: Reuse the same logic across different parts of your Odoo ecosystem.
Step 1: Module Scaffolding
We need a standard Odoo module structure. The key is correctly registering the frontend assets in the __manifest__.py.
'name': 'owl_new_arrivals',
'version': '18.0.1.0.0',
'category': 'Website',
'depends': ['website', 'sale_management'],
'data': [
'views/snippets.xml',
],
'assets': {
'web.assets_frontend': [
'owl_new_arrivals/static/src/js/new_arrivals.js',
'owl_new_arrivals/static/src/xml/new_arrivals.xml',
'owl_new_arrivals/static/src/css/style.scss',
],
},
Step 2: The Data Controller
Our OWL component needs an endpoint to talk to. We'll create a controller that returns the latest 4 products.
from odoo import http
from odoo.http import request
class NewArrivalsController(http.Controller):
@http.route('/api/new_arrivals', type='json', auth='public')
def get_new_arrivals(self):
domain = [('is_published', '=', True), ('image_1920', '!=', False)]
products = request.env['product.template'].search_read(
domain,
['name', 'list_price', 'currency_id', 'image_1920'],
limit=4,
order='create_date desc'
)
return products
Step 3: The OWL Component
This Javascript class handles the fetching logic. We use onWillStart to ensure data is ready before the component renders.
/** @odoo-module **/
import { Component, useState, onWillStart } from "@odoo/owl";
import { rpc } from "@web/core/network/rpc";
import { registry } from "@web/core/registry";
export class NewArrivals extends Component {
static template = "owl_new_arrivals.NewArrivalsTemplate";
setup() {
this.state = useState({ products: [] });
onWillStart(async () => {
this.state.products = await rpc("/api/new_arrivals");
});
}
}
// Register as a public component for the website
registry.category("public_components").add("owl_new_arrivals.NewArrivals", NewArrivals);
Step 4: The XML Views
First, define the component's internal template (what the card looks like). Then, define the snippet block that wraps it.
$
Finally, register the snippet in the Website Builder using the special <owl-component> tag.
Fresh Just In
Conclusion
You have now created a fully functional, dynamic snippet. Unlike traditional static snippets, this component fetches live data every time it renders. This architecture is perfect for flash sales, stock tickers, or personalized user dashboards.
Master Odoo Website Development?
Want to build advanced portals or ecommerce experiences using OWL? Our team specializes in high-performance Odoo frontend development.
