Client / Sector
Revilia Lab - botanical skincare and hair oils, direct-to-consumer
Market
Algeria, nationwide delivery across all 58 wilayas
Engagement
Brand and art direction, storefront engineering, commerce and measurement stack, ongoing content engine
Status / Year
Live since 2024, still in active production
The situation
Natural hair and skin oils are one of the most crowded categories in Algerian social commerce. The default way to sell them is a Facebook page, a phone number, a comment section full of price requests, and a courier called manually once a day. It works, and it caps you: the brand never owns a customer, never owns a catalogue, and never owns a story longer than a caption.
Revilia Lab wanted the opposite of that. The brief was a brand that reads like a fashion house rather than a pharmacy shelf: bold serif headlines, intimate macro video, slow scroll-driven storytelling - sitting on top of a commerce stack that behaves properly: collections, product pages, a cart, a checkout tuned to how Algerians actually buy, and a Journal that gives the brand something to rank for.
The commercial reality underneath that brief shapes every engineering decision. Prices are in dinars. Almost nobody pays with a card, so the checkout ends in cash on delivery and a phone number, not a payment authorisation. And because the growth channel is paid social, the storefront is not only a shop - it is the measurement instrument that tells Meta which creative produced which order. In a market with no online payment event to anchor on, that instrument has to be built deliberately or the ads engine optimises against noise.
What made this hard
Cash on delivery breaks the analytics loop
Everywhere else, the purchase signal comes from the payment processor. Here the order is a promise: a name, a phone number, a wilaya, and an intention to pay the courier at the door. The storefront itself has to decide what a conversion is and report it honestly, knowing the money has not moved yet.
Browser tracking is the least reliable half of the signal
Content blockers, privacy settings and lossy mobile sessions eat a meaningful share of browser-fired events. Relying on the pixel alone would have under-reported exactly the audiences the brand spends most against, and campaign optimisation degrades quietly rather than failing loudly.
One currency for the customer, another for the optimiser
The catalogue is priced and sold in dinars, but ad platforms optimise value against major currencies and compare campaigns across time. Reporting raw dinar amounts, or converting them against a moving rate, would make last month's return on ad spend incomparable with this month's.
Customer records are PII in a browser-first architecture
A single-page storefront talking straight to a hosted database is fast to build and dangerous to get wrong: the customer table holds phone numbers and delivery addresses. Locking it down with row-level security is the easy part - keeping the checkout working once an anonymous key can write but never read is the part that needs a pattern.
Video-first storytelling on mobile connections
The whole brand argument is carried by macro video and large editorial imagery. That argument has to load on a mid-range Android phone on a mobile network, or the story never gets told and the bounce happens before the first scroll.
How we approached it
We treated the storefront as two products that happen to share a domain: a brand film you can buy from, and a measurement layer that has to survive contact with a cash market. The brand work came first, because in this category the visual language is the product differentiator - but every engineering decision after it was made in service of a clean, deduplicated growth signal.
We also stayed on after launch. The same team that built the store runs the brand's content engine: product scenes, Arabic ritual-education carousels, before-and-after storytelling and AI-generated video ads, all produced inside the brand's midnight-and-gold world so the creative and the site look like one company rather than two vendors.
Brand and art direction
We built the visual system before a single screen: serif display type, a midnight-and-gold palette, and macro video as the primary storytelling medium rather than a decorative header. The rule we set was that every product page should be able to sell the product with the images alone.
Storefront engineering
A React single-page storefront over a hosted Postgres backend, with collections, product detail pages, cart, a cash-on-delivery checkout that resolves delivery against the national wilaya list, and a Journal for long-form brand content. Prices live in dinars in the database and never get converted for display.
From static hosting to an application server
The site originally shipped as static files. To own the growth signal we moved it into a containerised Node and Express server that serves the built application and hosts a first-party tracking endpoint alongside it, so the storefront and its measurement layer deploy as one unit.
The measurement layer
We wired the browser pixel and the server-side Conversions API to fire together for every commerce event, sharing a single event identifier so the platform deduplicates instead of double-counting. Purchase events carry hashed customer identifiers, and all reported values pass through one fixed currency convention.
Content engine and offer pages
We kept producing the brand's creative and shipped the merchandising surfaces it points at, including a dedicated bundle landing page with its own checkout so a campaign can send traffic to an offer rather than to a catalogue.
What we shipped
Storefront
- Editorial home with scroll-driven, video-led brand storytelling
- Collections and product detail pages built around macro imagery
- Cart and cash-on-delivery checkout with national wilaya delivery selection
- Readable product URLs mapped from slugs rather than raw record identifiers
- Journal for long-form brand and ingredient content
- Dedicated bundle landing page with its own conversion path
Commerce operations
- Admin-editable catalogue with dinar pricing
- Bundles created as ordinary catalogue products the brand can price and edit
- Order records written from the storefront with customer data kept read-protected
- Delivery pricing resolved per wilaya at checkout
- Configuration driven by environment rather than hard-coded values
Measurement and growth
- Browser pixel plus first-party server-side Conversions API endpoint
- Shared event identifiers across both surfaces for platform-side deduplication
- PageView, ViewContent, AddToCart, InitiateCheckout and Purchase coverage
- Hashed customer identifiers on purchase events
- A single fixed reporting-currency convention for all reported values
- A test-event channel for verifying instrumentation before campaigns run
Content engine
- Cinematic product scenes generated inside the brand world
- Arabic ritual-education carousels for organic and paid placements
- Before-and-after storytelling formats for the hair-oil line
- AI-generated video ads cut for feed and reels placements
- Creative produced against the same art direction as the storefront
Engineering decisions
The choices that shaped the build, and what each one traded away.
We replaced static hosting with an application server we own
The storefront could have stayed a pile of static files on a CDN, which is cheaper and simpler. We moved it into a small Node and Express container so the site could expose a first-party endpoint for server-side conversion reporting - which keeps the access token out of the browser and keeps the request from being blocked with the rest of the third-party traffic. The trade-off is real: we took on a container to build, ship and keep healthy, and because the client-side configuration is baked in at build time, rotating a key means a rebuild rather than a restart.
Every commerce event fires twice, on purpose
Each event is sent from the browser and from the server with the same event identifier. The browser copy carries the session context the platform trusts; the server copy carries the truth, and still arrives when the browser copy is blocked. The failure mode of this design is double-counted conversions, so the identifier is generated once at the call site and handed to both paths rather than derived independently on each side.
A fixed reporting-currency convention instead of a live exchange rate
Order values are stored in dinars and converted to a single major currency at a fixed, configurable divisor before they reach the ads platform. A live rate would have been more accurate on any given day and useless across time - campaign value would move because of the currency rather than because of the creative. We accepted that the reported figure drifts from real-world value as rates move: it is a measurement unit for optimisation, not an accounting record. The books stay in dinars.
Write-only client access to customer records
The customer table holds phone numbers and addresses, so it runs under row-level security with no public read policy at all. That breaks the conventional insert-then-read-back pattern every client library defaults to. The storefront now generates the customer identifier itself before writing and never reads the row back. The cost is that the client cannot confirm the write by reading it; the gain is a database where an anonymous key can never enumerate a customer list.
Bundles are products, not a bundle engine
The hero bundle is an ordinary catalogue record with a stable identifier and a readable slug, not a special product type with component logic. That means the brand can edit and reprice the offer without a developer, and the bundle gets a real product page and a real landing page for free. The trade-off is that component stock is not decremented automatically - the operator manages that - which is the right compromise at this catalogue size.
The outcome
Revilia Lab now sells from an owned storefront rather than a comment section. The brand controls its catalogue, its pricing, its story and its customer records, and the site carries the editorial weight the category usually lacks - the product pages are built to be convincing on their own, which is what lets paid traffic land directly on an offer instead of on a homepage.
The measurement layer is what makes the paid channel legible. Because every commerce event is reported from both the browser and the server against one deduplicated identifier and one consistent value unit, campaign figures stay comparable from week to week instead of moving with the reporting. That was the point of taking on a server we control rather than staying on static hosting.
The engagement did not end at launch. We continue to run the brand's content engine, which means the creative in the feed and the storefront it links to are designed by the same people against the same art direction - and new offers ship as merchandising surfaces rather than as one-off campaign pages.
2
Reporting surfaces per event
Every commerce event is sent from the browser pixel and from the server-side Conversions API with a shared identifier, so the platform deduplicates rather than double-counts.
58
Wilayas served at checkout
Delivery selection and cash-on-delivery pricing resolve against the full national wilaya list.
5
Instrumented commerce events
PageView, ViewContent, AddToCart, InitiateCheckout and Purchase, each dual-fired and value-normalised.
1
Container, two jobs
A single Node and Express image serves the built storefront and hosts the first-party tracking endpoint, so the shop and its measurement layer always ship together.
Honestly
The honest limitation of this build is baked into the market. In a cash-on-delivery economy the purchase event fires when the order is placed, not when the money is collected, and a share of orders is always refused at the door. Reported conversions are therefore optimistic by construction, and the true reconciliation still happens in the operations sheet rather than in the ads dashboard. We would rather say that plainly than quote a conversion figure that treats an intention as a payment.
The obvious next step is to close that loop: feed delivered-versus-ordered status back into the reported signal so the ads engine optimises toward orders that actually get paid for, not just orders that get placed. It is a bigger change than it sounds, because it requires the courier state to be as trustworthy as the checkout - and that is the piece of Algerian e-commerce infrastructure that is still catching up.
Frequently asked
Can a cash-on-delivery store still read as a premium editorial brand?
That was the brief for Revilia Lab. The storytelling layer is designed first, with serif display type, macro video and scroll-driven product pages, and the checkout underneath it resolves a phone number, a wilaya and a findable address instead of a payment token. Collecting the money at the door constrains the operations, not the art direction.
How do you track Facebook and Instagram ad conversions when there is no online payment?
We instrument the storefront itself as the source of truth. Every commerce event fires from the browser and from a first-party server endpoint with a shared identifier so the platform deduplicates, purchase events carry hashed customer identifiers, and all values are normalised to one fixed reporting currency so campaigns stay comparable over time.
Do you produce the product photography and ad creative as well as the website?
For Revilia Lab we do both. We run the brand's content engine, which covers product scenes, Arabic education carousels, before-and-after formats and AI-generated video ads, all built against the same art direction as the storefront, so the creative and the destination read as one brand.
What stack do you use for a direct-to-consumer store in Algeria?
A React storefront over a hosted Postgres backend with row-level security, served by a small Node and Express container that also hosts the server-side tracking endpoint. It keeps the site fast, keeps customer data read-protected, and keeps the growth signal first-party.
