There are three ways to add testimonials to your website: write the HTML yourself, build the section from your platform’s native blocks, or paste one embed script that renders them for you. Which one fits comes down to how often your testimonials change. The rest of this guide prices all three — setup, upkeep, page weight.
The short version:
- Hand-coded HTML is the lightest and cheapest route, but every future update means editing a page.
- Platform blocks (WordPress, Webflow, Wix, Squarespace) are quick to build and fine for a static set of quotes.
- A widget is one script tag, identical on every platform, and it updates itself when you approve a new testimonial.
- Custom-code embeds are plan-gated on some platforms — Squarespace, Webflow, Carrd, WordPress.com — while self-hosted WordPress, Shopify, Ghost, Framer, Bubble and Kajabi document no plan gate. Notion and Skool cannot run embeds at all.
- Whichever route you pick, ask on the collection form whether the words can be public, and every quote arrives ready to publish.
How to add testimonials to your website: the three routes
Every tutorial, plugin, and support doc on how to add testimonials to a website reduces to one of three routes. You write the markup yourself, you assemble the section from whatever blocks your site builder provides, or you paste a script tag that renders the testimonials for you. The first two put the content inside your page, where it stays until you edit it by hand. The third keeps the content in a separate tool and draws it onto the page on each visit.
| Route | Setup | Ongoing maintenance | Page weight | Requirements |
|---|---|---|---|---|
| Hand-coded HTML/CSS | Hours, needs code access | You edit a page for every change | Lightest possible | Comfort with code |
| Platform-native blocks | Under an hour in the editor | Manual edits, repeated per page | Light to moderate | None |
| Embedded widget (script tag) | Minutes | None; new testimonials flow through approval | One extra script request | Custom code is plan-gated on some platforms |
The rest of this guide walks through each route with the full bill attached: what it costs to set up, to keep current, and to load.
Route 1: hand-code the testimonial section
If you can write HTML, you can have a testimonial section live in an afternoon with zero dependencies. This is the lightest option a page can carry: no script, no plugin, no external request. A minimal, semantic version looks like this.
<section class="testimonials">
<figure>
<blockquote>"The onboarding took a week off our launch timeline."</blockquote>
<figcaption>Maria K., Head of Ops, Fieldstone</figcaption>
</figure>
</section>
Repeat the figure block per testimonial, add CSS for a grid or a single featured quote, and you are done. Use real names and roles where you have permission for them; a quote attributed to “A happy customer” persuades no one. If you are unsure what shape the section should take, wall, carousel, or single quote, start with the layout patterns for displaying testimonials and build the simplest one that fits. Eleven rendered examples show what each shape looks like once it is filled in.
What hand-coding actually costs
The bill arrives later. Every new testimonial is a code edit, a review, and a deploy. If the same quotes appear on your homepage, a landing page, and a pricing page, that is three edits per change. Nobody budgets time for this, so the section quietly freezes: the classic failure mode is a wall of quotes with dates from three years ago, which reads worse than no quotes at all, because visitors notice staleness. Hand-coding is the right call when you have a handful of strong testimonials, you expect them to hold for a year or more, and you would rather own every byte of the page than depend on a tool. It is the wrong call when testimonials keep arriving and you want the site to reflect that.
Route 2: your platform’s built-in blocks
Every major site builder can produce a testimonial section from its native elements, with no code and no external requests. The catch is the same everywhere: the content is part of the page layout, so keeping it current is manual work multiplied by the number of pages it appears on.
WordPress
WordPress runs about 41% of all websites, per W3Techs, so this is the most-documented path. In the block editor, a Quote or Pullquote block inside a Columns layout gets you a serviceable grid, and many themes ship ready-made testimonial patterns you can insert and edit. The plugin directory offers dedicated testimonial plugins too, though each one adds code that loads on your pages and needs updating. Note the split that matters later: self-hosted WordPress accepts any markup you give it, while WordPress.com restricts what free plans can embed. Both of those gates, and the block the script tag goes into, are walked through in installing a testimonial widget on WordPress.
Webflow
Webflow gives you the cleanest native structure of the four. Create a CMS Collection with fields for the quote, name, role, and photo, then bind a Collection List to it wherever testimonials should appear. Adding a testimonial becomes a CMS entry instead of a layout edit, and every bound page updates at once. You still curate and enter each item by hand, and the collection lives inside that one Webflow project; it cannot follow you to another site. If you would rather the testimonials outlive the project, the Code Embed route on Webflow is one element and one line.
Wix
In the Wix editor, a testimonial section is text and image elements arranged in a strip or grid, and many Wix templates include one pre-built. Repeater elements make the layout consistent: style one card and every entry inherits it. Updates remain manual edits in the editor, and reordering or pruning old quotes is drag-and-drop work you have to remember to do. The alternative that never needs the editor again is pasting a widget into a Wix embed box.
Squarespace
Squarespace handles a static set of quotes gracefully. Quote blocks render pull-quote styling out of the box, and list sections can present testimonial cards with images in the polished layouts the platform is known for. As with the others, the content is fixed in the page: adding a new testimonial means opening the editor, duplicating a block, and pasting text into it, on every page where testimonials appear. Squarespace’s Code block route removes that repetition, with the premium-plan caveat noted below.
Where platform blocks fall short
The shared weakness is not the build, which is genuinely quick. It is everything after. There is no pipeline from “customer said something great” to “it appears on the site”: you collect quotes elsewhere, track permission elsewhere, and paste by hand. Redesigns mean rebuilding the section from scratch. And if you run more than one site, or ever switch platforms, the work does not transfer. Platform blocks suit a marketing site with a deliberately curated, rarely-changing set of quotes. They fight you the moment testimonials become a stream instead of a snapshot.
Route 3: one script tag, identical on every platform
The third route moves testimonials out of your page and into a tool that renders them. You collect submissions with a form, approve the ones you want public, and paste a single script tag where the section should appear. A testimonial tool like Testymo generates the tag for you; this is the live demo widget, and it works pasted into any page that accepts HTML:
<script src="https://testymo.com/w/demo.js" async></script>
That one line is the entire integration, and it is the same line on WordPress, Shopify, Webflow, Wix, Squarespace, Ghost, Framer, or a hand-built static site. When you approve a new testimonial, the widget shows it on the next page load, with no edit to the site itself. A well-built embed keeps to strict rules: no cookies, no third-party requests, and hard style isolation — a shadow root gives you that without an iframe’s height-guessing and the layout shift that comes with it. Ask those questions of any widget vendor before pasting their tag.
Where the script tag goes, platform by platform
The paste step differs only in what each platform calls its custom-code element, and in which plans allow it. These gates apply to any custom code, not just testimonial widgets. The table below is the summary; each platform has a step-by-step walkthrough of its own, collected under testimonial widget setup by platform.
| Platform | Where to paste the tag | Fine print |
|---|---|---|
| WordPress (self-hosted) | A Custom HTML block in the editor, or a theme widget area | No plan gate — but saving a <script> needs the unfiltered_html capability, which single-site Administrators and Editors have, per WordPress.org |
| WordPress.com | Custom HTML block | Script tags need a plugin-enabled plan, per WordPress.com support |
| Webflow | The Embed element | Needs a paid Site plan or paid Workspace; not available on free Starter sites, per Webflow’s help center |
| Wix | An Embed HTML element, from the editor’s Add Elements panel | No documented plan gate on the element itself, per Wix’s Embed HTML article. The separate site-wide Custom Code route is the gated one: it needs a published site with a connected domain, per Wix support |
| Squarespace | A Code block | JavaScript in Code blocks is a premium feature, per Squarespace’s help center |
| Shopify | A Custom Liquid section in the theme editor | No gate on standard plans; the legacy Starter plan cannot customize themes, per Shopify’s help center. The practical check is whether your theme offers the section — Shopify’s own free themes all do |
| Framer | An Embed component with Type set to HTML | No documented plan requirement, per Framer’s help center — paid plans buy the custom domain and branding removal |
| Ghost | An HTML card in the editor | No documented gate on Ghost(Pro) or self-hosted, per Ghost’s help center |
| Carrd | An Embed element with Type set to Code | Embeds need Pro Standard ($19/year) or higher, per Carrd’s docs — and the free Pro trial does not include them |
| Notion | Nowhere, natively — Notion’s embed block takes a URL only | No Notion plan runs custom code, per Notion’s embed help. What works: a Notion-site builder like Super, which loads custom HTML from marked code blocks, or an embed block showing a page you host |
| Bubble | An HTML element from the palette | No documented gate on the element, per Bubble’s manual; taking the app live is what Bubble describes as the Starter plan’s job |
| Kajabi | A Custom Code block in the page builder | No plan gate on the block, per Kajabi’s help center — only the theme-template code editor is Pro-only, and an embed never needs it |
| Teachable | A Custom HTML block in the page editor | No plan gate, but new schools must ask Teachable Support to enable the block, per Teachable’s help center; the site-wide Code Snippets (Builder plan and above) are head-only, so they cannot place a visible widget |
| Podia | Nowhere per-page — the Embed tool takes URLs only | A script tag fits only the site-wide Third-party code field on paid plans, injected before the closing body tag, per Podia’s help center; its native Testimonials section covers in-page proof |
| Skool | Nowhere — no code runs on Skool | No plan runs custom code; embedding on Skool means pasting a video link from four providers, per Skool’s help center. What works: testimonial images on the About page, and the widget on the site the group card links to |
Where a platform does gate custom code, that gate is the route’s hard limit, and no widget vendor can route around it — nobody can put a script on a page the platform will not run scripts on. But it is not the blanket rule a free tier makes it feel like: self-hosted WordPress gates on the account’s permissions rather than on a plan, Wix documents no plan requirement on the Embed HTML element at all, Ghost documents no gate anywhere, and Kajabi gates only its theme editor — never the paste. Read your own row before assuming an upgrade is the price of entry.
The page-weight bill, honestly
Any third-party script is a dependency you did not write. It adds at least one network request, it runs code on your page, and if the vendor has an outage, the section renders empty. Weigh that before embedding anything, and measure the specific widget rather than trusting the category. The spread is wide: some widgets load an entire JavaScript framework plus analytics; others are a single small file. As a concrete data point, Testymo’s public demo widget measured as about 6 KB over the wire, one request, no follow-up fetches — the measurement method and numbers are in the page-speed guide. That figure covers the demo widget’s eight quotes, and the testimonials ride inside the script rather than arriving in a second request, so a wall of thirty weighs thirty quotes’ worth of text. That is still lighter than many hero images. But verify whatever you embed yourself.
Which route fits your site
Match the route to how your testimonials behave, not to what a tutorial happens to cover.
| Your situation | Best route |
|---|---|
| A few strong quotes, unlikely to change for a year, and you write code | Hand-coded HTML |
| A designed marketing site with a deliberately curated, static set | Platform blocks |
| Testimonials keep arriving and the site should stay current | Embedded widget |
| The same testimonials on several sites or platforms | Embedded widget |
| A strict no-third-party-scripts policy | Hand-coded HTML |
The routes also combine. Plenty of sites hand-code one flagship quote into the hero, where every byte and every millisecond counts, and let a widget run the full wall further down the page, where freshness matters more than raw weight. Before you add anything, it’s worth deciding which pages get a testimonial at all — the answer usually runs to about five, and rarely the five you would guess.
Nothing to add yet? Collect testimonials first
The embed step is the easy half. The harder half is having words worth showing, and no route fixes an empty section. If you are staring at a testimonial layout with nothing to put in it, start by asking: a short form with a few pointed questions, sent at the moment a customer has just gotten a result, outperforms a vague “any feedback?” months later. The scripts and timing are covered in how to ask for a testimonial, and if you have no customers to ask yet, collecting the first testimonials without clients covers what belongs in the section meanwhile. One habit saves you a lot of time later, whatever tooling you use: ask on the form whether the words can be public, and keep the answer with the entry. A quote you know you can publish goes live the day you get it; one you are unsure about sits in a folder for a year.
Frequently asked questions
Can I add testimonials to my website without a plugin?
Yes. Hand-coded HTML needs nothing installed, and platform-native blocks are built into the editor you already use. An embedded widget also needs no plugin; it is a script tag pasted into a custom-code element. Plugins are only one way of doing this on WordPress, and often the heaviest.
Will a testimonial widget slow my site down?
It depends entirely on the widget, so measure it before and after with a tool like PageSpeed Insights. Some load frameworks and tracking scripts; a lean one is a single small request. Check what the tag actually loads in your browser’s network tab, and prefer widgets that make no third-party requests.
Can I use the same testimonial widget on more than one website?
Generally yes. A script tag is plain HTML, so the same tag works on any page that accepts custom code, across different platforms. This is the main practical advantage over platform blocks: the testimonials live in one place, and every site embedding the tag stays current together.
Do I need permission to publish a customer’s testimonial?
Ask for it, and ask on the form rather than in a follow-up email. It takes the customer two seconds while they are already writing, and it means every quote you collect is one you can put live the same day. Getting permission in one step covers the wording and where the answer should live.