Add the SeggWat feedback button to your React application in minutes. Works seamlessly with Create React App, Next.js, Vite, and other React frameworks.
Quick Setup
The SeggWat button works with any React setup. Choose the method that fits your project:
Create React App
Next.js
Vite
Custom React Component
Add the script to your public/index.html file: <! DOCTYPE html >
< html lang = "en" >
< head >
< meta charset = "utf-8" />
< meta name = "viewport" content = "width=device-width, initial-scale=1" />
< title > React App </ title >
<!-- SeggWat Feedback Button -->
< script defer
src = "https://seggwat.com/static/widgets/v1/seggwat-feedback.js"
data-project-key = "YOUR_PROJECT_KEY"
data-button-color = "#61dafb" >
</ script >
</ head >
< body >
< div id = "root" ></ div >
</ body >
</ html >
The #61dafb color matches React’s official branding!
App Router (Next.js 13+) Add the script to your root layout: import type { Metadata } from 'next'
import Script from 'next/script'
import './globals.css'
export const metadata : Metadata = {
title: 'My Next.js App' ,
description: 'Built with Next.js' ,
}
export default function RootLayout ({
children ,
} : {
children : React . ReactNode
}) {
return (
< html lang = "en" >
< head >
< Script
src = "https://seggwat.com/static/widgets/v1/seggwat-feedback.js"
data-project-key = "YOUR_PROJECT_KEY"
data-button-color = "#000000"
strategy = "lazyOnload"
/>
</ head >
< body > { children } </ body >
</ html >
)
}
Pages Router (Next.js 12 and earlier) Add to pages/_app.tsx: import type { AppProps } from 'next/app'
import Script from 'next/script'
export default function App ({ Component , pageProps } : AppProps ) {
return (
<>
< Script
src = "https://seggwat.com/static/widgets/v1/seggwat-feedback.js"
data-project-key = "YOUR_PROJECT_KEY"
data-button-color = "#000000"
strategy = "lazyOnload"
/>
< Component { ... pageProps } />
</>
)
}
Use Next.js’s Script component with strategy="lazyOnload" for optimal performance.
Add the script to your index.html: <! DOCTYPE html >
< html lang = "en" >
< head >
< meta charset = "UTF-8" />
< link rel = "icon" type = "image/svg+xml" href = "/vite.svg" />
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" />
< title > Vite + React </ title >
<!-- SeggWat Feedback Button -->
< script defer
src = "https://seggwat.com/static/widgets/v1/seggwat-feedback.js"
data-project-key = "YOUR_PROJECT_KEY"
data-button-color = "#646cff" >
</ script >
</ head >
< body >
< div id = "root" ></ div >
< script type = "module" src = "/src/main.tsx" ></ script >
</ body >
</ html >
For more control, create a React component: components/FeedbackButton.tsx
import { useEffect } from 'react'
interface FeedbackButtonProps {
projectKey : string
buttonColor ?: string
buttonPosition ?: 'bottom-right' | 'right-side' | 'icon-only'
language ?: 'en' | 'de' | 'sv'
version ?: string
}
export function FeedbackButton ({
projectKey ,
buttonColor = '#2563eb' ,
buttonPosition = 'bottom-right' ,
language = 'en' ,
version ,
} : FeedbackButtonProps ) {
useEffect (() => {
// Create script element
const script = document . createElement ( 'script' )
script . src = 'https://seggwat.com/static/widgets/v1/seggwat-feedback.js'
script . defer = true
script . setAttribute ( 'data-project-key' , projectKey )
script . setAttribute ( 'data-button-color' , buttonColor )
script . setAttribute ( 'data-button-position' , buttonPosition )
script . setAttribute ( 'data-language' , language )
if ( version ) {
script . setAttribute ( 'data-version' , version )
}
// Add to document
document . head . appendChild ( script )
// Cleanup function
return () => {
document . head . removeChild ( script )
// Remove the button and modal from DOM
const button = document . getElementById ( 'seggwat-feedback-button' )
const modal = document . getElementById ( 'seggwat-feedback-modal-overlay' )
button ?. remove ()
modal ?. remove ()
}
}, [ projectKey , buttonColor , buttonPosition , language , version ])
return null // This component doesn't render anything
}
Then use it in your app: import { FeedbackButton } from './components/FeedbackButton'
import packageJson from '../package.json'
function App () {
return (
<>
< FeedbackButton
projectKey = "YOUR_PROJECT_KEY"
buttonColor = "#61dafb"
buttonPosition = "bottom-right"
language = "en"
version = { packageJson . version }
/>
< div className = "App" >
< h1 > My React App </ h1 >
{ /* Your app content */ }
</ div >
</>
)
}
export default App
Import version from package.json to automatically track your app version with each feedback submission.
Version Tracking
Track feedback against specific releases by adding the data-version attribute:
Next.js (Automatic)
Create React App
Vite
Import version directly from package.json: import Script from 'next/script'
import packageJson from '../package.json'
export default function RootLayout ({ children }) {
return (
< html lang = "en" >
< head >
< Script
src = "https://seggwat.com/static/widgets/v1/seggwat-feedback.js"
data-project-key = { process . env . NEXT_PUBLIC_SEGGWAT_PROJECT_KEY }
data-version = { packageJson . version }
strategy = "lazyOnload"
/>
</ head >
< body > { children } </ body >
</ html >
)
}
Every feedback submission will include your current version from package.json. Use environment variable to inject version at build time: {
"name" : "my-app" ,
"version" : "1.2.3" ,
"scripts" : {
"start" : "REACT_APP_VERSION=$npm_package_version react-scripts start" ,
"build" : "REACT_APP_VERSION=$npm_package_version react-scripts build"
}
}
Then use in component: import { FeedbackButton } from './components/FeedbackButton'
function App () {
return (
< FeedbackButton
projectKey = "YOUR_PROJECT_KEY"
version = { process . env . REACT_APP_VERSION }
/>
)
}
Configure Vite to expose version: import { defineConfig } from 'vite'
import { readFileSync } from 'fs'
const packageJson = JSON . parse (
readFileSync ( './package.json' , 'utf-8' )
)
export default defineConfig ({
define: {
'__APP_VERSION__' : JSON . stringify ( packageJson . version )
}
})
Use in component: import { FeedbackButton } from './components/FeedbackButton'
function App () {
return (
< FeedbackButton
projectKey = "YOUR_PROJECT_KEY"
version = { __APP_VERSION__ }
/>
)
}
TypeScript users, add to vite-env.d.ts: declare const __APP_VERSION__ : string
This component doesn’t render anything
Version Tracking Guide Learn more about automated version injection and CI/CD integration
Dynamic Updates
Update the feedback button appearance dynamically using the global API:
components/FeedbackSettings.tsx
import { useState } from 'react'
export function FeedbackSettings () {
const [ color , setColor ] = useState ( '#2563eb' )
const updateButtonColor = ( newColor : string ) => {
setColor ( newColor )
// Update SeggWat button appearance
if ( window . SeggwattFeedback ) {
window . SeggwattFeedback . updateAppearance ({
color: newColor
})
}
}
return (
< div >
< h3 > Customize Feedback Button </ h3 >
< button onClick = { () => updateButtonColor ( '#ef4444' ) } >
Red Theme
</ button >
< button onClick = { () => updateButtonColor ( '#10b981' ) } >
Green Theme
</ button >
< button onClick = { () => updateButtonColor ( '#3b82f6' ) } >
Blue Theme
</ button >
</ div >
)
}
TypeScript Support
Add type definitions for the SeggWat API:
interface SeggwatFeedback {
updateAppearance ( options : {
color ?: string
position ?: 'bottom-right' | 'right-side' | 'icon-only'
language ?: 'en' | 'de' | 'sv'
}) : Promise < void >
container : HTMLButtonElement
}
interface Window {
SeggwattFeedback ?: SeggwatFeedback
}
Now you get full autocomplete:
// TypeScript knows about SeggwattFeedback!
window . SeggwattFeedback ?. updateAppearance ({
color: '#ef4444' ,
position: 'bottom-right' ,
language: 'de'
})
React Router Integration
The feedback button works seamlessly with React Router - no special configuration needed:
import { BrowserRouter , Routes , Route } from 'react-router-dom'
function App () {
return (
< BrowserRouter >
{ /* Button appears on all routes */ }
< Routes >
< Route path = "/" element = { < Home /> } />
< Route path = "/about" element = { < About /> } />
< Route path = "/contact" element = { < Contact /> } />
</ Routes >
</ BrowserRouter >
)
}
The feedback button automatically captures the current route path when users submit feedback, helping you understand which pages need improvements.
Environment Variables
Use environment variables to manage your project key across environments:
Create React App
Next.js
Vite
// .env.production
REACT_APP_SEGGWAT_PROJECT_KEY = your - production - key
// .env.development
REACT_APP_SEGGWAT_PROJECT_KEY = your - dev - key
// In your component
const projectKey = process . env . REACT_APP_SEGGWAT_PROJECT_KEY || ''
Then use in your component:
< FeedbackButton projectKey = { projectKey } />
Advanced Examples
Conditional Rendering
Show the feedback button only on specific routes or for certain users:
import { useLocation } from 'react-router-dom'
import { FeedbackButton } from './components/FeedbackButton'
function App () {
const location = useLocation ()
const isProductionRoute = location . pathname . startsWith ( '/app' )
return (
<>
{ /* Only show on production routes */ }
{ isProductionRoute && (
< FeedbackButton
projectKey = "YOUR_PROJECT_KEY"
buttonColor = "#10b981"
/>
) }
{ /* Your app content */ }
</>
)
}
Theme Integration
Sync the feedback button with your app’s theme:
import { useState , useEffect } from 'react'
import { FeedbackButton } from './components/FeedbackButton'
function App () {
const [ theme , setTheme ] = useState < 'light' | 'dark' >( 'light' )
useEffect (() => {
// Update button color when theme changes
const color = theme === 'dark' ? '#ffffff' : '#000000'
window . SeggwattFeedback ?. updateAppearance ({ color })
}, [ theme ])
return (
< div className = { theme } >
< FeedbackButton
projectKey = "YOUR_PROJECT_KEY"
buttonColor = { theme === 'dark' ? '#ffffff' : '#000000' }
/>
< button onClick = { () => setTheme ( theme === 'light' ? 'dark' : 'light' ) } >
Toggle Theme
</ button >
</ div >
)
}
Custom Hook
Create a custom hook for easier integration:
import { useEffect , useState } from 'react'
interface UseSeggwatOptions {
projectKey : string
buttonColor ?: string
buttonPosition ?: 'bottom-right' | 'right-side' | 'icon-only'
language ?: 'en' | 'de' | 'sv'
version ?: string
}
export function useSeggwat ({
projectKey ,
buttonColor = '#2563eb' ,
buttonPosition = 'bottom-right' ,
language = 'en' ,
version ,
} : UseSeggwatOptions ) {
const [ isLoaded , setIsLoaded ] = useState ( false )
useEffect (() => {
const script = document . createElement ( 'script' )
script . src = 'https://seggwat.com/static/widgets/v1/seggwat-feedback.js'
script . defer = true
script . setAttribute ( 'data-project-key' , projectKey )
script . setAttribute ( 'data-button-color' , buttonColor )
script . setAttribute ( 'data-button-position' , buttonPosition )
script . setAttribute ( 'data-language' , language )
if ( version ) {
script . setAttribute ( 'data-version' , version )
}
script . onload = () => setIsLoaded ( true )
document . head . appendChild ( script )
return () => {
document . head . removeChild ( script )
document . getElementById ( 'seggwat-feedback-button' )?. remove ()
document . getElementById ( 'seggwat-feedback-modal-overlay' )?. remove ()
}
}, [ projectKey , buttonColor , buttonPosition , language , version ])
const updateAppearance = ( options : {
color ?: string
position ?: 'bottom-right' | 'right-side' | 'icon-only'
language ?: 'en' | 'de' | 'sv'
}) => {
window . SeggwattFeedback ?. updateAppearance ( options )
}
return { isLoaded , updateAppearance }
}
Usage:
import { useSeggwat } from './hooks/useSeggwat'
import packageJson from '../package.json'
function App () {
const { isLoaded , updateAppearance } = useSeggwat ({
projectKey: 'YOUR_PROJECT_KEY' ,
buttonColor: '#61dafb' ,
version: packageJson . version ,
})
return (
< div >
{ isLoaded && < p > Feedback button loaded! </ p > }
< button onClick = { () => updateAppearance ({ color: '#ef4444' }) } >
Change to Red
</ button >
</ div >
)
}
React Native
The SeggWat feedback button is designed for web applications. For React Native mobile apps, consider using the API directly:
import { useState } from 'react'
import { View , TextInput , Button , Alert } from 'react-native'
export function FeedbackForm () {
const [ message , setMessage ] = useState ( '' )
const submitFeedback = async () => {
try {
const response = await fetch ( 'https://seggwat.com/api/v1/feedback/submit' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
project_key: 'YOUR_PROJECT_KEY' ,
message ,
path: 'mobile-app' ,
}),
})
if ( response . ok ) {
Alert . alert ( 'Success' , 'Thank you for your feedback!' )
setMessage ( '' )
}
} catch ( error ) {
Alert . alert ( 'Error' , 'Failed to send feedback' )
}
}
return (
< View >
< TextInput
value = { message }
onChangeText = { setMessage }
placeholder = "Share your feedback..."
multiline
/>
< Button title = "Send Feedback" onPress = { submitFeedback } />
</ View >
)
}
API Reference Learn more about the SeggWat REST API
Troubleshooting
Button not appearing in React app
Button disappears on route change
TypeScript errors with window.SeggwattFeedback
Add type definitions: interface Window {
SeggwattFeedback ?: {
updateAppearance ( options : any ) : void
container : HTMLButtonElement
}
}
Place this in a types/global.d.ts file or at the top of your component.
The SeggWat button works only in the browser. To avoid SSR issues:
Use Next.js Script component with strategy="lazyOnload"
Add checks: if (typeof window !== 'undefined')
Don’t call window.SeggwattFeedback during server-side rendering
Content Security Policy (CSP) issues
If your app uses CSP headers, allow SeggWat scripts: script-src 'self' https://seggwat.com;
connect-src 'self' https://seggwat.com;
style-src 'self' https://seggwat.com 'unsafe-inline';
For Next.js, add to next.config.js: const securityHeaders = [
{
key: 'Content-Security-Policy' ,
value: "script-src 'self' https://seggwat.com; ..."
}
]
Best Practices
Load asynchronously Use defer or async attributes to avoid blocking page render. Next.js’s Script component handles this automatically.
Environment-based keys Use different project keys for development, staging, and production to keep feedback organized.
Add to root layout Place the script in your app’s root layout or HTML file so it appears on all routes without re-mounting.
Type safety Add TypeScript definitions for window.SeggwattFeedback to get autocomplete and type checking.
Example Projects
Minimal Create React App
npx create-react-app my-app
cd my-app
Edit public/index.html:
< script defer
src = "https://seggwat.com/static/widgets/v1/seggwat-feedback.js"
data-project-key = "YOUR_PROJECT_KEY" >
</ script >
Minimal Next.js App
npx create-next-app@latest my-app
cd my-app
Edit app/layout.tsx:
import Script from 'next/script'
export default function RootLayout ({ children }) {
return (
< html >
< head >
< Script
src = "https://seggwat.com/static/widgets/v1/seggwat-feedback.js"
data-project-key = "YOUR_PROJECT_KEY"
strategy = "lazyOnload"
/>
</ head >
< body > { children } </ body >
</ html >
)
}
Next Steps