← Writing

I built a review tool that can’t game reviews

The full loop. The private rating gates the owner alert, not the public link.
The full loop. The private rating gates the owner alert, not the public link.

Every local business owner has been sold the same thing. A tool that “helps you get more five-star reviews.” Send a link after a visit, watch the rating climb.

Look at how most of them actually work and there’s a filter in the middle.

The customer gets asked how their visit went before anyone shows them a Google link. Rate it four or five stars, here’s where to post it publicly. Rate it one or two, and you get a private feedback form instead — a polite dead end. The public rating only ever sees the good half.

It works. It’s also called review gating, and it breaks the terms of every major review platform. Google’s policy is explicit that you can’t selectively solicit positive reviews. Businesses using these tools are usually unaware they’re exposed.

I wanted to find out whether you could build something that got the same outcome — more reviews, fewer angry surprises — without the filter.

The constraint

One rule, decided before any code: every customer gets the same public review link, regardless of how they rated.

That sounds like giving up the product’s main trick. It isn’t, because the trick was never the filter — it was the timing. Most unhappy customers don’t post a one-star review out of malice. They post it because nobody asked them first, and the review is the only channel they have.

So the private rating stays. It just doesn’t decide who gets the link. It decides who the owner hears about immediately.

The bar for that is deliberately low: anything below five stars raises the alert. Four stars is not a complaint, but it is someone telling you something was slightly off, and that is worth a phone call while they still remember what it was.

A customer who rates two stars still gets the Google link. They’re also far less likely to use it angrily, because someone already listened and the owner is on the phone before the day is out. The rating average that ends up public is the real one — it’s just attached to a business that fixes things faster.

Why that distinction matters

Put the two models side by side and the difference isn’t subtle.

Same first step, completely different second one.
Same first step, completely different second one.

The gated version produces a better-looking number. The ungated version produces a better business — and doesn’t put the owner one policy audit away from having their reviews wiped.

That’s the whole pitch, and it’s the reason the compliance language sits on the marketing page instead of being buried. It’s the differentiator.

What the customer actually sees

The customer-facing page is the part I rewrote most. Whatever is happening in the backend, this is a person on a phone who did not ask to be emailed.

One question, five stars, no account, no app.
One question, five stars, no account, no app.

No login. No app. A single-use link that only the recipient holds, on a page that loads in well under a second at the edge. One question, five buttons, done. Anything more and the response rate collapses.

The engineering was not where I expected

I assumed the hard part would be the email. It wasn’t.

Multi-tenant isolation

Every business’s data has to be invisible to every other business. That’s easy to say and easy to get almost right — one missing WHERE business_id = ? on one query and you’ve leaked a competitor’s customer list.

So it isn’t enforced in application code. It’s enforced in Postgres with row-level security, and there’s an automated test that spins up a throwaway database, creates two businesses, and asserts that one genuinely cannot see the other. It runs on every build. If someone writes a careless query later, the build fails before it ships.

The public feedback page goes further — it runs as a separate worker with its own restricted database role that can only touch the handful of columns it needs.

Email deliverability is its own discipline

Getting an email sent took an afternoon. Getting it delivered took considerably longer.

A brand-new domain has no sending reputation, so the first messages land in Promotions or Spam even with SPF, DKIM and DMARC all passing correctly. That’s not a bug you can fix — it’s reputation you have to earn. What helped: authenticating the domain properly, turning off click tracking so links point at the real domain instead of a tracking redirect, and accepting that the first weeks are warm-up.

One failure was pure comedy. Password reset emails silently never arrived. Every log said success. The cause was a single digit — the SMTP port was set to 586 instead of 587. A dead port. The mail server simply couldn’t connect, and the anti-enumeration design meant the API cheerfully returned success either way.

Nothing sends itself unless something wakes it up

The app runs on Cloudflare Workers, which don’t sit around waiting. A request created in the dashboard just becomes a row marked pending.

That needed a second, separate scheduled worker that fires every minute, claims any pending requests past their retry time, and sends them. Splitting it out from the main app was the right call — the sender keeps running even while the app is being redeployed.

Where it actually stands

ReviewWard is live at reviewward.com, on its own domain, taking real subscriptions through Stripe with a 14-day trial. Signup, onboarding, sending, the rating loop, the owner alert, billing and password reset all work end to end. A brand-new user can go from the homepage to a working dashboard without me touching anything.

The honest gap: SMS. Text messages get read far more than email for this kind of request, and the code path exists. What’s missing is A2P 10DLC carrier registration — a paperwork queue, not a build. Until it clears, the channel stays switched off rather than half-working.

That’s the part nobody tells you about shipping a real SaaS. The last ten percent isn’t code. It’s domain authentication, carrier registration, payment verification, and legal review — and none of it can be rushed by working harder.

What I’d tell anyone building something similar

Pick the constraint that makes the product harder and more defensible, then let it drive the architecture. “Never gate a review” ruled out the easy version of this product on day one. It also produced something a business owner can use without wondering whether it’ll get them penalised.

Constraints like that are worth more than features.

ReviewWard is live

Running in production, taking real subscriptions, sending real email. You can visit ReviewWard, or read the technical breakdown.

Building something like this?

Tell me what you have in mind. The first conversation is free.

Start a project
UNIVRSLL Labs is a trading name of UNIVRSLL LLC, a limited liability company registered in Michigan, USA · Entity ID 900257530
7401 Williamson Street, Dearborn, Michigan 48126, US · contact@univrsll.com
Websites · Applications · AI tools · AI lessons
Built and maintained by one person.

Discover more from UNIVRSLL Labs

Subscribe now to keep reading and get access to the full archive.

Continue reading