
Social Proof You Can Click: How We Run Our Testimonial Wall With Senja
Every quote on the Notis homepage links to a public source. Here is how we collect them with Senja, and why we self-host a pinned copy of the widget loader.
Every SaaS homepage has a testimonial section. Almost none of them are checkable.
Three smiling faces, three quotes, a first name and a job title. No link, no source, no way to tell whether the person exists. As a buyer I've learned to scroll past it. As a founder I didn't want to build one.
So when we put a wall of love on the Notis homepage, the requirement was that every quote leads somewhere. Senja is how we do that.

Proof you can click
The testimonials on our homepage come from Senja, and the important bit is that each one has a public page behind it. There's a "Verified on Senja" link that takes you to the testimonial's own URL — not a screenshot, not a card we typed, the submission as it was given.
That changes the conversation. If someone doubts a quote, the answer is a link rather than my word. And it changes what I'm willing to put on the page, because anything I'd be uncomfortable having checked doesn't go up.
Collection is the other half. Senja lets people submit a written or video testimonial from a link, and it handles the awkward part — reminding, formatting, permissions — so I'm not personally chasing anyone for a paragraph. For a founder-led product where I'm the one who'd have to send that message, the difference between "a tool does this" and "I do this" is the difference between having testimonials and not.
The engineering problem nobody mentions
Here is where it got interesting, and where I'd argue we do something slightly unusual.
Testimonial widgets are third-party JavaScript. Third-party JavaScript on your homepage means: a script you don't control, fetched from a domain you don't control, executing in your users' browsers, on the page where you're asking people to trust you with their data.
We run a security posture we're public about. Loading an unpinned cross-origin script on the homepage didn't fit it.
So for the main wall of love, we self-host a pinned copy of the Senja loader. It's served same-origin from our own assets, not fetched from a third-party CDN at render time.
That solves the integrity question in a way subresource integrity hashes don't. An SRI hash would break the widget the next time Senja shipped an update — a page that fails loudly on a vendor deploy is not an improvement. A frozen same-origin copy fails safe: worst case it keeps showing the version we last reviewed.

The trade-off, and how we handle it
Pinning has an obvious cost. Senja bakes the selected testimonials and their order into the per-widget file. If I edit the widget on senja.io and don't re-download, the site keeps showing yesterday's selection.
That's a stale-content bug that would be invisible for weeks. So it's a build step: a refresh-senja script pulls the current copy, and a companion check fails CI if the committed copy is stale. Update the widget, run the refresh, commit, deploy.
Is that more ceremony than pasting a script tag? Yes. But it converts "a vendor script runs on our homepage" into "a reviewed artefact ships with our site," and the staleness risk into a check that's impossible to forget.
The other cost is weight. The pinned loader is around 1.3 MB — it carries the testimonial content, so it's not small. Our wall of love sits well below the fold, and there's no reason for someone who bounces from the hero to download a megabyte of reviews they'll never see. So we only inject the script when the section approaches the viewport, using an IntersectionObserver, with a straightforward fallback for browsers that don't have one.
Net effect: full social proof, zero cost to initial page load, no unreviewed third-party script on the critical path.
Why social proof is different for an AI product
I'll be honest about why this matters more to us than to a normal SaaS.
People are wary of AI assistants, and they should be. You're asking someone to connect their email, their calendar, their notes, and then let software act on their behalf. Feature lists don't move that needle. Neither do anonymous quotes.
What moves it is a named person saying what they actually use it for, with a link proving they said it. That's a fundamentally different asset from marketing copy, and it's the only kind I'm comfortable putting next to a signup button.
It also keeps me honest. A testimonial wall you can't edit into fiction is a feedback loop. When the quotes drift toward one use case, that's telling me something about who we're actually for.
If you're setting this up
Four things I'd do again:
- Make every quote link to a public source. Unverifiable proof isn't proof, it's decoration.
- Decide how you feel about third-party scripts on your homepage before you paste one. If you have a published security posture, your marketing page is part of it.
- If you pin, automate the staleness check. A frozen copy with no refresh discipline is a slow-motion bug.
- Lazy-load below-the-fold widgets. Social proof shouldn't tax people who never scroll to it.
Notis is a founder-led product, still growing from voice-to-Notion capture into broader connected-tool workflows. The people in our wall of love are the reason I know which parts of that are working.
Senja collects them, and gives me a link I can stand behind.

Flo is the founder of Mind the Flo, an Agentic Studio specialized into messaging and voice agents.
Related posts
The Emails an AI Assistant Owes You: How Notis Uses Customer.io
Agents fail quietly. Here is the full inventory of operational emails Notis sends through Customer.io, and why triggers belong in code while copy belongs in the ESP.
One State Layer for an AI Assistant: How Notis Uses Supabase
Conversations, documents, automations and durable agent sessions all live in one Supabase project — and why the file-sharing trade-off is worth defending out loud.
You Can't Debug an Agent From a Log Line: How We Trace Notis With Langfuse
How Notis uses Langfuse to see what an agent actually did, why we wrap the SDK to enforce masking, and the thread leak that taught us to cache clients.