# Quizzings > Collect customer reviews and embed them on your own site. This file is the complete integration guide. Everything needed to add the widget is below. There is no SDK to install and no API key. ## Concepts A business has an id (a UUID) and a public review link. Reviews are left by anyone with the link, with no account. Only reviews with status "published" are ever returned by the API; a business can hide a review from their site but cannot edit or delete one. The site id is shown in the Quizzings dashboard under Embed. ## Option 1: script tag Works on any website, including plain HTML, WordPress, Webflow and Framer.
The script renders into every element matching the target selector. Place the div wherever the reviews should appear. The script tag itself can go anywhere. ### Script tag attributes data-site required. The business id from the dashboard. data-layout grid | list | badge. Default grid. data-limit how many reviews to fetch, 1 to 50. Default 6. data-accent any CSS colour. Default #007aff. Overrides both themes. data-target CSS selector for the container. Default [data-quizzings="reviews"] The product was called Proofly before, so the default selector also still matches [data-proofly="reviews"]. Existing installs keep working untouched. Use data-quizzings for anything new. ### Layouts grid responsive cards. For a homepage section or a landing page. list a score header over stacked rows. For a dedicated reviews page. badge compact score summary. For a pricing page, sidebar or footer. ### Styling notes The widget renders in a shadow root, so host page CSS cannot restyle its internals and its CSS cannot leak out. Two properties are inherited from the host on purpose: font-family and color. To make the widget match the surrounding design, set those on the container element:
Do not attempt to target internal classes such as .pf-card from the host page. They are not reachable and are not a stable API. Use data-accent and the inherited font instead. The widget emits Schema.org AggregateRating JSON-LD into the light DOM next to the container, so it is visible to search crawlers. ## Option 2: React or Next.js There is no npm package. Copy this component into the project. It has no dependencies beyond React. "use client"; import { useEffect, useState } from "react"; const QUIZZINGS_ORIGIN = "https://reviews-rhf8acz8h-nas-projects-4df7577e.vercel.app"; type QuizzingsData = { business: { name: string; url: string | null; reviewUrl: string }; summary: { score: number; count: number }; reviews: { id: string; rating: number; body: string; name: string; verified: boolean; createdAt: string; }[]; }; export function QuizzingsReviews({ site, limit = 6, }: { site: string; limit?: number; }) { const [data, setData] = useState(null); useEffect(() => { let cancelled = false; fetch(`${QUIZZINGS_ORIGIN}/api/widget/${site}?limit=${limit}`) .then((r) => (r.ok ? r.json() : Promise.reject(r.status))) .then((d) => { if (!cancelled) setData(d); }) .catch(() => {}); return () => { cancelled = true; }; }, [site, limit]); if (!data || data.reviews.length === 0) return null; return ( ); } Style it to match the surrounding page. The markup above is intentionally unstyled so it does not fight an existing design system. For a server component, fetch the same URL directly and skip the effect: const res = await fetch(`https://reviews-rhf8acz8h-nas-projects-4df7577e.vercel.app/api/widget/${site}?limit=6`, { next: { revalidate: 300 }, }); ## Option 3: the JSON API GET https://reviews-rhf8acz8h-nas-projects-4df7577e.vercel.app/api/widget/{siteId}?limit=6 Public, no authentication, CORS open to all origins. Cached for 60 seconds at the edge with a 300 second stale-while-revalidate window. Response: { "business": { "id": "uuid", "name": "Hearthline", "url": "https://hearthline.com", "logo": "https://.../logo.png", "reviewUrl": "https://reviews-rhf8acz8h-nas-projects-4df7577e.vercel.app/r/hearthline" }, "summary": { "score": 4.8, "count": 127 }, "reviews": [ { "id": "uuid", "rating": 5, "body": "Free text written by the customer.", "name": "Alex Mercer", "verified": false, "createdAt": "2026-01-30T10:12:00.000Z" } ] } 404 with {"error":"not_found"} for an unknown site id. Reviewer email addresses are never returned. "verified" is currently false on all reviews; it will become true for reviews collected through an emailed invitation once that ships. Do not render a verification badge when it is false. ## Collecting reviews Share the business review link with customers: https://reviews-rhf8acz8h-nas-projects-4df7577e.vercel.app/r/{slug} No account is required to leave a review. Reviews appear in the widget immediately. ## Checklist for an agent doing this integration 1. Confirm the site id with the user. Do not invent one. 2. Pick the layout from where it is being placed, using the layout table above. 3. For plain HTML, add the script tag and container. For React, paste the component and style it to match the existing design system. 4. Verify by loading the page and confirming reviews render. If the container is empty, check the browser console for a [quizzings] warning. 5. Do not commit the site id to a public repo if the user prefers it in an environment variable. It is not a secret, but it is theirs.