Docs

Documentation

Learn how to use FeedSense to collect, analyze, and act on customer feedback.

Installation Guide

The FeedSense feedback widget takes just 2 minutes to install. Choose the method that fits your stack.

Step 1: Get Your API Key

  1. Log in to your FeedSense dashboard
  2. Navigate to Settings → API
  3. Click Generate API Key
  4. Copy the key immediately - it is only shown once

Step 2: Install the Widget

Option A: npm (React / Next.js)

Install the SDK package:

Terminal
npm install @feedsense/sdk

Initialize the SDK in your app:

typescript
import FeedSense from '@feedsense/sdk';

await FeedSense.init({
  apiKey: 'your-api-key',
  apiUrl: 'https://api.feedsense.co'
});

Next.js with FeedSenseProvider

For Next.js apps, create a provider component that wraps your layout. This is how the FeedSense landing site itself integrates the widget:

components/providers/FeedSenseProvider.tsx
'use client';

import { useEffect, useRef } from 'react';

interface FeedSenseProviderProps {
  apiKey: string;
  apiUrl?: string;
  children: React.ReactNode;
}

export function FeedSenseProvider({
  apiKey,
  apiUrl,
  children
}: FeedSenseProviderProps) {
  const isInitialized = useRef(false);

  useEffect(() => {
    if (isInitialized.current) {
      return;
    }

    if (!apiKey || apiKey === 'your-api-key-placeholder') {
      console.warn('[FeedSense] No valid API key provided. Widget will not be initialized.');
      return;
    }

    let destroyed = false;

    import('@feedsense/sdk')
      .then((sdk) => {
        if (destroyed) return;

        return sdk.default.init({
          apiKey,
          ...(apiUrl && { apiUrl }),
        });
      })
      .then(() => {
        if (destroyed) {
          import('@feedsense/sdk').then((sdk) => sdk.default.destroy());
          return;
        }
        isInitialized.current = true;
      })
      .catch((error: unknown) => {
        console.error('[FeedSense] Failed to initialize widget:', error);
      });

    return () => {
      destroyed = true;
      if (isInitialized.current) {
        import('@feedsense/sdk').then((sdk) => sdk.default.destroy());
        isInitialized.current = false;
      }
    };
  }, [apiKey, apiUrl]);

  return <>{children}</>;
}

Then wrap your app in app/layout.tsx:

app/layout.tsx
import { FeedSenseProvider } from '@/components/providers/FeedSenseProvider';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <FeedSenseProvider
          apiKey={process.env.NEXT_PUBLIC_FEEDSENSE_API_KEY || ''}
          apiUrl={process.env.NEXT_PUBLIC_FEEDSENSE_API_URL}
        >
          {children}
        </FeedSenseProvider>
      </body>
    </html>
  );
}

Programmatic Control with useFeedSense Hook

You can open and close the widget programmatically using a custom hook:

hooks/useFeedSense.ts
'use client';

import { useCallback, useState, useEffect, useRef } from 'react';

export function useFeedSense() {
  const [isAvailable, setIsAvailable] = useState(false);
  const sdkRef = useRef<typeof import('@feedsense/sdk') | null>(null);

  useEffect(() => {
    let cancelled = false;

    const loadAndCheck = async () => {
      try {
        const FeedSense = await import('@feedsense/sdk');
        sdkRef.current = FeedSense;
        if (!cancelled) setIsAvailable(FeedSense.isInitialized());
      } catch {
        if (!cancelled) setIsAvailable(false);
      }
    };

    loadAndCheck();

    const interval = setInterval(() => {
      if (sdkRef.current) {
        const ready = sdkRef.current.isInitialized();
        if (!cancelled) setIsAvailable(ready);
        if (ready) clearInterval(interval);
      }
    }, 1000);

    return () => {
      cancelled = true;
      clearInterval(interval);
    };
  }, []);

  const open = useCallback(async () => {
    const sdk = sdkRef.current ?? await import('@feedsense/sdk');
    if (sdk.isInitialized()) sdk.open();
  }, []);

  const close = useCallback(async () => {
    const sdk = sdkRef.current ?? await import('@feedsense/sdk');
    if (sdk.isInitialized()) sdk.close();
  }, []);

  return { open, close, isAvailable };
}

Use it in any component:

tsx
const { open, isAvailable } = useFeedSense();

return (
  <button onClick={open} disabled={!isAvailable}>
    Send Feedback
  </button>
);

Option B: Script Tag (Plain HTML)

Add this snippet before the closing </body> tag:

html
<script src="https://unpkg.com/@feedsense/sdk@latest/dist/index.umd.js"></script>
<script>
  FeedSense.init({
    apiKey: 'your-api-key',
    apiUrl: 'https://api.feedsense.co'
  });
</script>

Step 3: Verify Installation

  1. Visit your website
  2. Look for the feedback tab on the right side of the page
  3. Click it to test the feedback form
  4. You should see test feedback appear in your dashboard within seconds

Configuration Options

The basic setup only requires apiKey. The following options are available:

OptionTypeDefaultDescription
apiKeystring-Your FeedSense API key (required)
apiUrlstringhttps://api.feedsense.coAPI endpoint URL
onSubmitfunction-Callback invoked after successful feedback submission
onErrorfunction-Callback invoked when submission fails (falls back to alert if not provided)
themeobject-Widget customization (v1.3.0+): colors, position, dark mode, custom text. Merged with the theme configured in your dashboard

Example with callbacks:

typescript
FeedSense.init({
  apiKey: 'your-api-key',
  apiUrl: 'https://api.feedsense.co',
  onSubmit: (feedback) => {
    console.log('Feedback submitted:', feedback);
  },
  onError: (error) => {
    console.error('Submission failed:', error);
  },
});

Identifying Users (v1.3.0+)

Attach the signed-in user's identity to their feedback so you can follow up and segment by account:

typescript
// after your user signs in
FeedSense.identify({
  userId: 'user_123',
  email: '[email protected]',
  name: 'Jane Doe',
});

// on logout
FeedSense.reset();

Identity persists across page reloads until reset() is called. All fields are optional - send what you have.

Troubleshooting

Widget not appearing?

  • Check that your API key is correct and has been generated in Settings → API
  • For script tag: ensure the script is before the closing </body> tag
  • For npm: make sure the SDK is initialized before rendering
  • Clear your browser cache and refresh
  • Check browser console for errors

Feedback not submitting?

  • Verify your project is active in the dashboard
  • Check that your API key has not been revoked
  • Ensure the apiUrl is correct
  • Check browser console for network errors

Related Docs

Need Help?

Something not working? Contact our support team