Loyalz started as internal tooling at zest.agency. This page is the long version: what the agency does, what broke, and what we built because of it.
ZEST.AGENCY · 2015
LOYALZ · 2023
FOUNDER
Karol MajewskiFounder, Loyalz · zest.agency
In 2023 I had one problem and one grant. The problem was that every loyalty programme I could buy for a client was either a plastic card or a plugin nobody opened twice. The grant was European Funds money, and what it really bought was the right to build the thing properly instead of in the evenings.
The first Loyalz did retention and nothing else, and it ran on Web3. In 2023 that sounded like the future. By 2024 it sounded like something you had to apologise for — our own FAQ was still answering questions about NFTs and gas fees while the merchants I was actually sitting with wanted points, cashback, and a voucher that worked at checkout. None of them wanted to learn what a wallet was in order to give somebody five percent back.
So we spent two years rebuilding it without the chain underneath. Points, cashback, benefits, levels, collections, quests — the mechanics a shop asks for by name, and nothing it never asked for. That is the retention half, and it is the half the grant paid for.
The second half came from the agency floor rather than from a roadmap. It began narrowly: read the creative, work out which ad was actually carrying an account, because knowing that an ad works is not enough information to brief the next one. Then the models got good enough that the same layer could make the creative rather than only rank it, and then good enough to run the campaigns it made. Analysis, production, management — in that order, and each step only because the one before it had stopped being the bottleneck.
The agency runs on it daily. Client campaigns at zest.agency are planned, ranked, cut and reported inside Loyalz, which means the awkward edges are found by us, on accounts we are accountable for, before they ever reach anybody else. That is also why it is built for two readers at once: the brand that wants to know what a customer cost and what they went on to be worth, and the agency that has to answer that question for thirty brands before Monday lunch.
Named services, named channels, named partnerships. This is the part that makes the origin story checkable rather than charming — the agency sells the same four things it built the tool out of. Its own line for the work is performance you can see in the P&L.
zest.agencyPerformance agency
Search and paid social on Google, Meta, TikTok and LinkedIn, run for stable sales scaling rather than for a good-looking week. This is the practice that produced the ranking and the pause rules.
GA4 and Tag Manager implementation, server-side tracking and consent handling, A/B testing wired to the system where the sale is actually recorded. This is the work that turned into Insights.
Serial production of user-generated video formats and ad graphics, made in volume specifically to bring acquisition cost down. This is why creative analysis was the first thing built on the acquisition side.
SERIAL OUTPUTranked on store revenue
Design and build for shops and campaign pages, with the tracking installed as part of the build rather than bolted on afterwards. A campaign is only as measurable as the page it lands on.
Two of the agency's working rules ended up as product decisions rather than slogans. The results the agency publishes are its own figures on its own site, which is the right way to read them.
Long form of what the homepage says in three sentences: four platforms, four ROAS figures, a spreadsheet, a client asking why nothing matched.
The scene repeated itself: four ad platforms reporting four different ROAS figures, a spreadsheet where someone reconciled them by hand, and a client asking why none of it matched what their store actually took. We were the ones who had to answer that on Monday.
So we built the layer that normalises every source into one shape, to stop reconciling manually. Then ranking, because a report with no decision attached is a prettier spreadsheet. Then creative analysis, because “this ad works” is not enough information to brief the next one. And when acquisition cost kept climbing faster than margins, we built the other half — the loyalty side — because the cheapest customer available to our clients was the one they already had.
The agency still runs on it every day. Campaigns for e-commerce and B2B clients are planned, cut and reported inside Loyalz, which means every awkward edge gets found by us before it reaches you.
The sum of platform ROAS never matched the invoice. This artefact is the whole justification for decision 03 below.
None of these came from a workshop. Every one of them exists because something went wrong on an account we were accountable for, in front of a client who was entitled to an answer.
A client read the weekly report, then opened the dashboard, and found the two praising different creatives on the same account in the same week. Both were correct. The report ranked on one window and one conversion definition, the dashboard on another, and nobody had ever written down which was the real one — because until somebody put them side by side, nobody had to.
The fix was not a better report. It was deciding, once, what the sentence “this is the best ad” means, and making every surface read that one definition: the ranking, the assistant, the weekly report, the pause rules. A number that changes depending on which screen you are looking at is not a measurement, it is an opinion with a decimal point.
An early automation did exactly what it was told. A new campaign had a poor first afternoon, the rule saw a cost per acquisition above target, and it paused the campaign on day one — before the platform had left the learning phase, on a sample too small to mean anything. The rule was right about the arithmetic and wrong about the world.
Now no rule can fire on an ad without delivery history behind it. Every automation carries a spend threshold as well as a performance one, and the threshold is a precondition rather than a setting somebody remembers to fill in. An automation that can act on noise will eventually act on noise, and it will do it at the worst possible moment.
The Monday report above is this one. Four platforms, four returns, each one confidently claiming the same order. Add them up and the total revenue exceeds what the shop actually took, sometimes by a third. Every platform counts a conversion it can see, and several of them can see the same one.
So the denominator moved. Revenue comes from the shop, not from the pixel, and platform figures are treated as claims to be reconciled against it rather than as the number. It makes the reported result lower and it makes it true, and only one of those two properties survives a conversation with a finance director.
“Who paused my ad?” is a question an agency gets asked, and the honest answer that week was that we were not sure — a rule had fired, or somebody had clicked, and there was no record that distinguished the two. Trust does not survive many of those.
Every automated action now writes a line: what changed, what triggered it, which account, and when. It is unglamorous and it is the feature that makes handing automation to a client possible at all, because the price of letting software touch a live budget is being able to say afterwards exactly what it did.
Loyalz is built by the team that runs client campaigns at zest.agency. Anything new goes onto real accounts with real budgets here first, so the problems turn up on our side before they reach yours.






Twenty minutes, live, on your data. We compute your fraction while you watch.
Book a demo — 20 min →