npm package: @inov-ai/feedback-widget
Description: Modern React feedback widget with surveys, analytics, and Next.js 15 support. Collect user feedback and run surveys in your SaaS applications.
Author: inov-ai
Latest version: 1.0.2

# @inov-ai/feedback-widget

A modern, customizable React feedback widget with surveys, feedback collection, and analytics. Perfect for SaaS applications with full Next.js 15 support and TypeScript.

## About inov-ai

[inov-ai](https://www.inov-ai.tech/) is a comprehensive feedback collection and analytics platform designed to help businesses gather valuable insights from their users. With advanced analytics, real-time feedback processing, and intelligent survey management, Inov-AI empowers companies to make data-driven decisions and improve their products based on actual user feedback.

**To get started with this widget, you'll need to:**
1. Sign up for a free account at [https://www.inov-ai.tech/](https://www.inov-ai.tech/)
2. Create a new project in your dashboard
3. Get your unique site key
4. Install and configure this widget in your application

## Features

- ✅ **Next.js 15 Compatible** - No CSP issues, SSR-safe, hydration-friendly
- ✅ **TypeScript Support** - Full type safety out of the box
- ✅ **Dual Collection Methods** - Quick feedback + detailed surveys
- ✅ **Smart Path Control** - Show widget only on specific routes
- ✅ **Theme Detection** - Auto-detects light/dark themes or use custom
- ✅ **Highly Customizable** - Colors, positions, triggers, animations
- ✅ **Zero Dependencies** - Only requires React as peer dependency
- ✅ **Mobile Responsive** - Works perfectly on all devices
- ✅ **Real-time Analytics** - Track feedback and survey responses

## Installation

```bash
npm install @inov-ai/feedback-widget
# or
yarn add @inov-ai/feedback-widget
# or
pnpm add @inov-ai/feedback-widget
```

## Quick Start

The simplest way to get started is to add the widget to your app with minimal configuration:

### 1. Basic Setup

```jsx
import { InovaiWidget } from '@inov-ai/feedback-widget';

function App() {
  return (
    <div>
      {/* Your app content */}
      <h1>My Amazing SaaS App</h1>
      
      {/* Add the feedback widget */}
      <InovaiWidget siteKey="your-site-key" />
    </div>
  );
}
```

### 2. Complete Example (Recommended)

This is the most common setup that works great for most applications:

```jsx
import { InovaiWidget } from '@inov-ai/feedback-widget';

function App() {
  return (
    <div>
      {/* Your app content */}
      <h1>My SaaS Dashboard</h1>
      
      {/* Feedback widget with full configuration */}
      <InovaiWidget
        siteKey="your-site-key"
        primaryColor="#f97316"
        fontFamily="Inter, system-ui, -apple-system, sans-serif"
        fontSize="16px"
        buttonRadius="8px"
        position="bottom-right"
        buttonText="Feedback"
        buttonIcon="💬"
        theme="auto"
        animation="slide"
        trigger="manual"
        triggerDelay={0}
        surveyFrequency="every-visit"
        minimized={false}
        feedbackTypes={["Bug", "Feature", "Suggestion", "Question"]}
        paths={["/", "/dashboard", "/feedback", "/analytics"]}
        onSubmit={(data) => {
          console.log('Feedback submitted:', data);
          // Integrate with your analytics or logging system
        }}
        onError={(error) => {
          console.error('Widget error:', error);
        }}
      />
    </div>
  );
}
```

### 3. Next.js 15 Setup

```jsx
// app/layout.tsx (App Router) or pages/_app.tsx (Pages Router)
import { InovaiWidget } from '@inov-ai/feedback-widget';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        {/* Add feedback widget to every page */}
        <InovaiWidget
          siteKey={process.env.NEXT_PUBLIC_FEEDBACK_SITE_KEY}
          primaryColor="#f97316"
          position="bottom-right"
          theme="auto"
          paths={["/dashboard", "/app", "/settings"]} // Only show on specific routes
        />
      </body>
    </html>
  );
}
```

## Configuration Options

### Required Props

| Prop | Type | Description |
|------|------|-------------|
| `siteKey` | `string` | Your unique site key from inov-ai dashboard |

### Appearance Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `primaryColor` | `string` | `#f97316` | Main color for buttons and highlights |
| `textColor` | `string` | Auto-detected | Text color (auto-detected from theme) |
| `backgroundColor` | `string` | Auto-detected | Modal background color |
| `theme` | `'light' \| 'dark' \| 'auto' \| 'system'` | `auto` | Color theme preference |
| `fontFamily` | `string` | `'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'` | Font family |
| `fontSize` | `string` | `16px` | Base font size |
| `buttonRadius` | `string` | `8px` | Border radius for buttons |
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | `bottom-right` | Widget position |
| `buttonText` | `string` | `Feedback` | Text on the trigger button |
| `buttonIcon` | `string` | `''` | Icon/emoji for the button |
| `animation` | `'slide' \| 'fade' \| 'none'` | `slide` | Opening animation |

### Behavior Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `trigger` | `'manual' \| 'auto' \| 'timer' \| 'scroll' \| 'exit'` | `manual` | How the widget opens |
| `triggerDelay` | `number` | `0` | Delay in milliseconds for auto triggers |
| `paths` | `string[]` | `[]` | URL paths where widget should appear (empty = all paths) |
| `surveyFrequency` | `'once' \| 'every-visit' \| 'daily' \| 'weekly'` | `every-visit` | How often to allow feedback |
| `minimized` | `boolean` | `false` | Start in minimized state |
| `feedbackTypes` | `string[]` | `['Feature Request', 'Bug Report', 'Integration', 'Question']` | Available feedback categories |

### Event Props

| Prop | Type | Description |
|------|------|-------------|
| `onOpen` | `() => void` | Called when widget opens |
| `onClose` | `() => void` | Called when widget closes |
| `onSubmit` | `(data: FeedbackSubmission) => void` | Called when feedback is submitted |
| `onError` | `(error: Error) => void` | Called when an error occurs |

## Path Configuration

The `paths` prop allows you to control where the widget appears:

```jsx
// Show on specific pages only
<InovaiWidget 
  siteKey="your-key"
  paths={["/", "/dashboard", "/settings"]}
/>

// Show on all dashboard routes
<InovaiWidget 
  siteKey="your-key"
  paths={["/dashboard*"]}
/>

// Show everywhere (default)
<InovaiWidget 
  siteKey="your-key"
  // paths prop omitted or empty array
/>
```

## Survey Integration

The widget automatically fetches and displays surveys from your inov-ai dashboard. Users can:

1. **Quick Feedback**: Submit general feedback with categories
2. **Surveys**: Answer detailed survey questions when available

## Advanced Examples

### With Custom Styling

```jsx
        .fb-widget-button {
          box-shadow: 0 4px 12px rgba(0,0,0,0.15);
## Advanced Examples

### With Custom Styling

```jsx
<InovaiWidget
  siteKey="your-site-key"
  primaryColor="#6366f1"
  theme="dark"
  position="bottom-left"
  buttonText="Help Us Improve"
  buttonIcon="📝"
  customCSS={`
    [data-feedback-widget] {
      --feedback-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
    }
  `}
/>
```

### With Analytics Integration

```jsx
<InovaiWidget
  siteKey="your-site-key"
  onSubmit={(data) => {
    // Send to your analytics
    analytics.track('Feedback Submitted', {
      category: data.category,
      page: data.metadata.page_url,
      rating: data.rating
    });
    
    // Show success message
    toast.success('Thank you for your feedback!');
  }}
  onError={(error) => {
    // Log errors
    console.error('Feedback widget error:', error);
    Sentry.captureException(error);
  }}
/>
```

### Timer-based Trigger

```jsx
<InovaiWidget
  siteKey="your-site-key"
  trigger="timer"
  triggerDelay={30000} // Show after 30 seconds
  surveyFrequency="once" // Only show once per user
/>
```

### Path-specific Configuration

```jsx
// Show different configurations on different routes
function App() {
  const { pathname } = useLocation();
  
  if (pathname.startsWith('/dashboard')) {
    return (
      <InovaiWidget
        siteKey="your-site-key"
        feedbackTypes={["Bug Report", "Feature Request", "Performance Issue"]}
        paths={["/dashboard*"]}
      />
    );
  }
  
  if (pathname === '/') {
    return (
      <InovaiWidget
        siteKey="your-site-key"
        feedbackTypes={["General Feedback", "Question"]}
        trigger="timer"
        triggerDelay={60000}
        paths={["/"]}
      />
    );
  }
  
  return null;
}
```

## TypeScript Support

Full TypeScript support with exported types:

```tsx
import { 
  InovaiWidget, 
  FeedbackConfig, 
  FeedbackSubmission,
  Survey 
} from '@inov-ai/feedback-widget';

const config: FeedbackConfig = {
  siteKey: 'your-site-key',
  primaryColor: '#f97316',
  theme: 'auto'
};

const handleSubmit = (data: FeedbackSubmission) => {
  console.log('Feedback received:', data);
};

function App() {
  return <InovaiWidget {...config} onSubmit={handleSubmit} />;
}
```

## Migration from Script Widget

If you're migrating from the script-based widget, here's how the props map:

| Script Attribute | React Prop | Notes |
|-------------------|------------|-------|
| `site_key` | `siteKey` | ✅ Same functionality |
| `data-primary-color` | `primaryColor` | ✅ Same functionality |
| `data-theme` | `theme` | ✅ Same functionality |
| `data-position` | `position` | ✅ Same functionality |
| `data-button-text` | `buttonText` | ✅ Same functionality |
| `data-paths` | `paths` | ✅ Same functionality |
| `data-feedback-types` | `feedbackTypes` | ✅ Same functionality |
| `data-trigger` | `trigger` | ✅ Same functionality |

## Troubleshooting

### Widget not appearing?

1. **Check paths configuration**: Make sure current route is in `paths` array
2. **Verify siteKey**: Ensure your site key is correct
3. **Check browser console**: Look for error messages

### Surveys not loading?

1. **Verify site key**: Must match your inov-ai dashboard
2. **Check active surveys**: Ensure you have active surveys in your dashboard
3. **Network issues**: Check browser network tab for failed requests

### Styling issues?

1. **CSS conflicts**: Use `customCSS` prop to override styles
2. **Theme detection**: Set explicit `theme` if auto-detection fails
3. **Z-index issues**: Widget uses z-index: 999999

## Support

- 📖 **Documentation**: [https://docs.inov-ai.tech](https://docs.inov-ai.tech)
- 💬 **Discord**: [Join our community](https://discord.gg/inov-ai)
- 📧 **Email**: support@inov-ai.tech
- 🐛 **Issues**: [GitHub Issues](https://github.com/godbright/inov-ai-package/issues)
- 🔗 **Repository**: [https://github.com/godbright/inov-ai-package.git](https://github.com/godbright/inov-ai-package.git)

## License

MIT License - see LICENSE file for details.
  );
}
```

### useThemeDetection

Detect the current theme:

```jsx
import { useThemeDetection } from '@inov-ai/feedback-widget';

function MyComponent() {
  const theme = useThemeDetection(); // 'light' | 'dark'
  
  return <div>Current theme: {theme}</div>;
}
```

## Path Monitoring

Control which pages show the widget:

```jsx
<InovaiWidget
  siteKey="your-site-key"
  paths={[
    '/dashboard/*',    // All dashboard pages
    '/app/settings',   // Specific page
    '/blog/*',         // All blog pages
  ]}
/>
```

## Environment Variables

For Next.js projects, use environment variables:

```bash
# .env.local
NEXT_PUBLIC_FEEDBACK_SITE_KEY=your-site-key
```

```jsx
<InovaiWidget
  siteKey={process.env.NEXT_PUBLIC_FEEDBACK_SITE_KEY}
/>
```

## Triggers

### Manual (Default)
Widget only opens when user clicks the button or you call `openWidget()`.

### Auto
Widget opens immediately when the page loads.

### Timer
Widget opens after a specified delay:

```jsx
<InovaiWidget
  trigger="timer"
  triggerDelay={5000} // 5 seconds
/>
```

### Scroll
Widget opens when user scrolls 50% down the page:

```jsx
<InovaiWidget trigger="scroll" />
```

### Exit Intent
Widget opens when user moves mouse towards browser top (exit intent):

```jsx
<InovaiWidget trigger="exit" />
```

## Styling

### CSS Variables
The widget respects CSS custom properties:

```css
:root {
  --feedback-primary-color: #f97316;
  --feedback-text-color: #111827;
  --feedback-background-color: #ffffff;
}
```

### Custom CSS
Add custom styles:

```jsx
<InovaiWidget
  customCSS={`
    .fb-widget-button {
      box-shadow: 0 8px 25px rgba(0,0,0,0.15);
      transform: scale(1.1);
    }
    
    .fb-widget-modal {
      backdrop-filter: blur(10px);
    }
  `}
/>
```

## TypeScript

Full TypeScript support with exported types:

```typescript
import type { 
  FeedbackConfig, 
  FeedbackSubmission,
  Survey,
  SurveyQuestion 
} from '@inov-ai/feedback-widget';

const config: FeedbackConfig = {
  siteKey: 'your-site-key',
  primaryColor: '#f97316',
  // ... other options
};
```

## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

MIT License - see [LICENSE](LICENSE) for details.

## Support

- 📧 Email: support@inov-ai.tech
- 📖 Documentation: https://docs.inov-ai.tech
- 🐛 Issues: https://github.com/godbright/inov-ai-package/issues
- 🔗 Repository: https://github.com/godbright/inov-ai-package.git