</>

How to add Pinnote to any website or web app

Pinnote is one script tag. Put it on every page, ideally just before </body>. It loads asynchronously, adds nothing to your bundle and stays idle unless the page was opened with a review link.

About 2 minutes · No developer needed (for most sites)

Your Pinnote code looks like this

Pinnote code
<script src="https://www.pinnote.xyz/widget.js" data-site="YOUR_SITE_ID" defer></script>

Copy your own code from Pinnote (Websites, your website, Install). It has your website's ID instead of YOUR_SITE_ID. Don't have an account? Create one free.

Steps

  1. In Pinnote, open Websites, choose your website and open the Install tab. Click Copy code. The code already contains your website's ID.
  2. Add the code to your site's main template or layout, before </body>. Framework examples are below.
  3. Deploy the change.
  4. Open your review link (the Review links tab in Pinnote). The Pinnote toolbar appears at the bottom of the page. Normal visitors never see it.

Examples

Plain HTML

index.html
  ...
  <script src="https://www.pinnote.xyz/widget.js" data-site="YOUR_SITE_ID" defer></script>
</body>

React (Vite, Create React App) or Angular

Add the line to index.html (Angular: src/index.html), before </body>.

Next.js (App Router)

app/layout.tsx
import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script src="https://www.pinnote.xyz/widget.js" data-site="YOUR_SITE_ID" strategy="afterInteractive" />
      </body>
    </html>
  );
}

Next.js (Pages Router)

Add the same <Script> line to pages/_app.tsx, next to <Component {...pageProps} />.

Nuxt 3

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [{ src: "https://www.pinnote.xyz/widget.js", "data-site": "YOUR_SITE_ID", defer: true }],
    },
  },
});

Astro

In your base layout, before </body>. Keep is:inline so Astro doesn't bundle it:

src/layouts/Layout.astro
<script is:inline src="https://www.pinnote.xyz/widget.js" data-site="YOUR_SITE_ID" defer></script>

Single-page apps are supported: the toolbar follows route changes and shows the feedback for each page.

Content Security Policy

If your site sends a Content-Security-Policy header, allow Pinnote:

CSP additions
script-src  https://www.pinnote.xyz
connect-src https://www.pinnote.xyz
img-src     https://www.pinnote.xyz https://*.public.blob.vercel-storage.com blob: data:
media-src   https://www.pinnote.xyz https://*.public.blob.vercel-storage.com blob:
style-src   'unsafe-inline'

The toolbar uses inline styles inside its own Shadow DOM, so it never clashes with your CSS. If your policy can't allow inline styles, tell us.

Troubleshooting

Staging and preview deployments

Add each address (for example staging.example.com or a Vercel/Netlify preview domain) under Settings › Allowed domains for this website in Pinnote.

“Feedback is not enabled for this domain”

The page's address isn't in the website's allowed domains. Add it under Settings › Allowed domains. The www and bare domains count as the same.

Need a hand? Email hello@pinnote.xyz and we'll help you set it up.
Try the live demo