Events

Learn how to listen for and respond to SDK events in the Feedhog JavaScript SDK.

Events

The Feedhog SDK emits events when important actions occur. Use event listeners to react to user actions, track analytics, or update your UI.

Event Types

EventPayloadDescription
identifyIdentifiedUserUser was successfully identified
submitFeedbackListItemFeedback was submitted
vote{ feedbackId: string, result: VoteResult }Vote was toggled
errorErrorAn error occurred
resetundefinedUser data was cleared

on(event, handler)

Subscribe to an event:

feedhog.on(event: string, handler: (payload: unknown) => void): void

off(event, handler)

Unsubscribe from an event:

feedhog.off(event: string, handler: (payload: unknown) => void): void

Event Examples

identify Event

Fired when a user is successfully identified:

import Feedhog from '@feedhog/js';
import type { IdentifiedUser } from '@feedhog/js';

const feedhog = new Feedhog({ apiKey: 'fhpk_your_public_key' });

feedhog.on('identify', (user: IdentifiedUser) => {
  console.log('User identified:', user.id);
  console.log('Email:', user.email);
  console.log('Created at:', user.createdAt);

  // Track in analytics
  analytics.identify(user.id, {
    email: user.email,
    name: user.name
  });
});

// Trigger the event
await feedhog.identify({
  externalId: 'user-123',
  email: 'john@example.com'
});

submit Event

Fired when feedback is successfully submitted:

import Feedhog from '@feedhog/js';
import type { FeedbackListItem } from '@feedhog/js';

const feedhog = new Feedhog({ apiKey: 'fhpk_your_public_key' });

feedhog.on('submit', (feedback: FeedbackListItem) => {
  console.log('Feedback submitted:', feedback.id);
  console.log('Title:', feedback.title);
  console.log('Type:', feedback.type);

  // Show success notification
  toast.success('Thank you for your feedback!');

  // Track in analytics
  analytics.track('Feedback Submitted', {
    feedbackId: feedback.id,
    type: feedback.type
  });
});

// Trigger the event
await feedhog.submit({
  title: 'Add dark mode',
  type: 'idea'
});

vote Event

Fired when a vote is toggled:

import Feedhog from '@feedhog/js';
import type { VoteResult } from '@feedhog/js';

const feedhog = new Feedhog({ apiKey: 'fhpk_your_public_key' });

feedhog.on('vote', ({ feedbackId, result }: { feedbackId: string; result: VoteResult }) => {
  console.log('Vote on:', feedbackId);
  console.log('Voted:', result.voted);
  console.log('Total votes:', result.voteCount);

  // Track in analytics
  analytics.track(result.voted ? 'Upvoted' : 'Removed Vote', {
    feedbackId,
    voteCount: result.voteCount
  });
});

// Trigger the event
await feedhog.vote('fb_abc123');

error Event

Fired when any SDK operation fails:

import Feedhog from '@feedhog/js';

const feedhog = new Feedhog({ apiKey: 'fhpk_your_public_key' });

feedhog.on('error', (error: Error) => {
  console.error('Feedhog error:', error.message);

  // Send to error tracking
  Sentry.captureException(error);

  // Show user-friendly message
  toast.error('Something went wrong. Please try again.');
});

// This will trigger the error event
try {
  await feedhog.submit({ title: '' }); // Empty title
} catch (error) {
  // Error is also thrown, but event is emitted first
}

reset Event

Fired when user data is cleared:

import Feedhog from '@feedhog/js';

const feedhog = new Feedhog({ apiKey: 'fhpk_your_public_key' });

feedhog.on('reset', () => {
  console.log('User data cleared');

  // Clear local state
  setCurrentUser(null);

  // Track in analytics
  analytics.reset();
});

// Trigger the event
feedhog.reset();

Removing Event Listeners

Always remove event listeners when they're no longer needed:

import Feedhog from '@feedhog/js';
import type { FeedbackListItem } from '@feedhog/js';

const feedhog = new Feedhog({ apiKey: 'fhpk_your_public_key' });

// Define the handler
function handleSubmit(feedback: FeedbackListItem) {
  console.log('Submitted:', feedback.id);
}

// Add listener
feedhog.on('submit', handleSubmit);

// Remove listener when done
feedhog.off('submit', handleSubmit);

React Integration

Use events with React hooks:

'use client';

import { useEffect, useCallback } from 'react';
import Feedhog from '@feedhog/js';
import type { FeedbackListItem, IdentifiedUser } from '@feedhog/js';
import { toast } from 'sonner';

const feedhog = new Feedhog({
  apiKey: process.env.NEXT_PUBLIC_FEEDHOG_API_KEY!
});

export function useFeedhogEvents() {
  const handleIdentify = useCallback((user: IdentifiedUser) => {
    console.log('User identified:', user.id);
  }, []);

  const handleSubmit = useCallback((feedback: FeedbackListItem) => {
    toast.success('Feedback submitted!', {
      description: feedback.title
    });
  }, []);

  const handleError = useCallback((error: Error) => {
    toast.error('Something went wrong', {
      description: error.message
    });
  }, []);

  useEffect(() => {
    // Add listeners
    feedhog.on('identify', handleIdentify);
    feedhog.on('submit', handleSubmit);
    feedhog.on('error', handleError);

    // Cleanup on unmount
    return () => {
      feedhog.off('identify', handleIdentify);
      feedhog.off('submit', handleSubmit);
      feedhog.off('error', handleError);
    };
  }, [handleIdentify, handleSubmit, handleError]);

  return feedhog;
}

Usage in Components

'use client';

import { useFeedhogEvents } from '@/hooks/use-feedhog-events';

export function FeedbackProvider({ children }: { children: React.ReactNode }) {
  // Set up event listeners
  useFeedhogEvents();

  return <>{children}</>;
}

Analytics Integration

Track all Feedhog events in your analytics provider:

import Feedhog from '@feedhog/js';

const feedhog = new Feedhog({ apiKey: 'fhpk_your_public_key' });

// Identify
feedhog.on('identify', (user) => {
  analytics.identify(user.id, {
    email: user.email,
    name: user.name
  });
});

// Submit
feedhog.on('submit', (feedback) => {
  analytics.track('feedback_submitted', {
    feedback_id: feedback.id,
    feedback_type: feedback.type,
    feedback_title: feedback.title
  });
});

// Vote
feedhog.on('vote', ({ feedbackId, result }) => {
  analytics.track(result.voted ? 'feedback_upvoted' : 'feedback_vote_removed', {
    feedback_id: feedbackId,
    vote_count: result.voteCount
  });
});

// Error
feedhog.on('error', (error) => {
  analytics.track('feedhog_error', {
    error_message: error.message
  });
});

Global Error Handling

Set up a global error handler for all SDK operations:

import Feedhog, { FeedhogApiError } from '@feedhog/js';

const feedhog = new Feedhog({ apiKey: 'fhpk_your_public_key' });

feedhog.on('error', (error) => {
  if (error instanceof FeedhogApiError) {
    switch (error.status) {
      case 401:
        console.error('Authentication failed - check your API key');
        break;
      case 403:
        console.error('Access denied');
        break;
      case 404:
        console.error('Resource not found');
        break;
      case 429:
        console.error('Rate limited - slow down requests');
        break;
      case 500:
        console.error('Server error - try again later');
        break;
      default:
        console.error('API error:', error.message);
    }

    if (error.details) {
      console.error('Validation errors:', error.details.fieldErrors);
    }
  } else {
    console.error('Unexpected error:', error);
  }
});