Plain HTML installation
Static HTML Site Testimonial Widget Embed
On a hand-written site there is no builder in the way. Put the StoryProof div in the section of your HTML file where testimonials belong, add the script once near the end of the body, upload the file, and you are done. The only things that usually go wrong are a missing script, a duplicated one, or a Content Security Policy that does not list the script’s host.
- A ready section of markup with the widget div
- Where the script goes, and why once is enough
- The CSP check for sites that send one
Code generator
Markup for your HTML files
Enter the widget id. Part 1 is a section you can drop into the body of any page. Part 2 goes once per page, just before the closing body tag, or in the footer partial your pages share.
Part 1 · In the page body, where testimonials should appear
index.html (or any page) › inside <main>
<section class="testimonials" aria-labelledby="testimonials-heading">
<h2 id="testimonials-heading">What customers say</h2>
<div data-storyproof-widget="YOUR_WIDGET_ID"></div>
</section>Part 2 · Once per page, before </body>
Same file, or your shared footer include
<script src="https://app.storyproof.io/embed.js" async></script>Save, upload the changed files to your host, and load the live page with the browser console open. A red line mentioning Content Security Policy means the header needs the script host added.
The markup is generated in your browser; the id is not stored.
The problem, solved
Hand-coded testimonials versus a StoryProof widget
- Problem 1
Every new quote is a redeploy
Static testimonials are paragraphs in a file, so adding one means editing HTML, committing and uploading again.
How StoryProof solves it
The file holds one div. You decide which approved testimonials the widget shows in StoryProof, so the HTML does not change when the selection does.
- Problem 2
Video praise means hosting files myself
Adding a customer video to a static site means encoding, uploading and writing a player for each clip.
How StoryProof solves it
Customers record video, audio or text through one StoryProof link in the browser, and the widget displays what you approve.
- Problem 3
Footer copied into twenty files
On a site without includes, every page has its own copy of the footer, so it is easy to paste the script twice or forget it on one page.
How StoryProof solves it
The script only needs to appear once per page, and one copy fills every StoryProof div on that page, so add it to the footer block and nowhere else.
- Problem 4
I would rather not write carousel code
Sliders, grids and responsive breakpoints for testimonials are a weekend of CSS and JavaScript.
How StoryProof solves it
Choose a layout in StoryProof, from walls and carousels to compact badges, and the widget handles its own arrangement.
In StoryProof
Add it to a static site
Step 1 of 4
Paste the section
Open the page file and paste Part 1 where testimonials belong, usually inside main after the content they support. Adjust the heading text to suit the page.
Step 2 of 4
Add the script once
Paste Part 2 just before the closing body tag. If your pages share a footer include or a static generator layout, put it there so every page gets exactly one copy.
Step 3 of 4
Update the CSP if you have one
If your host or server sends a Content-Security-Policy header with a script-src directive, add app.storyproof.io to it. A script from a host that is not listed is blocked.
Step 4 of 4
Deploy and check the console
Upload or deploy, open the live page, and check the browser console for errors. The async script loads while the page keeps rendering, so the rest of the page is not held up.
Where the script line goes
Before you start
Things to watch
CSP may need more than script-src
A strict policy can also restrict images, media and connections. StoryProof has not published a full list of hosts the widget needs, so read the console errors and allow what is blocked.
Keep the src as given
Load embed.js from the address in the snippet rather than copying the file into your own folder. A local copy would not receive changes made to the hosted file.
Height changes after load
The widget fills in after the script runs, so the section grows. Give it a sensible min-height in your CSS if layout shift matters to you.
Badge on lower plans
Until Pro, a small "Powered by StoryProof" badge appears under widgets.
Web standards as read on 2026-11-12
The async and CSP notes follow MDN as read on 2026-11-12. The steps have not been tried on a specific host; hosts expose header settings in different places.
FAQ
Questions people ask
Short answers to what usually comes up next.
Can I put the script in the head instead?
It is async, so it will not block parsing either way. Before the closing body tag keeps all third-party scripts in one predictable place.
Do I need jQuery or a framework?
No. The embed is a div and one script tag, and works on a page with no other JavaScript.
How do I style the widget to match my CSS?
Style the section and heading around it with your own CSS. The widget itself is set up through its layout in StoryProof.
Can two different widgets go on one page?
Yes. Paste two divs with their own widget ids and keep a single script line.
Still have a question? Ask the StoryProof team or book a demo.
Stop editing HTML for every new quote
Collect and approve testimonials in StoryProof, then add one div and one script to your site.
Sources
- <script>: The Script element, MDN Web Docs. Checked 2026-11-12.
- Content-Security-Policy: script-src directive, MDN Web Docs. Checked 2026-11-12.
Last updated 2026-11-12.