bookwiz.io / lib / analytics.ts
analytics.ts
Raw
// Analytics service for BookWiz platform
export const GTM_ID = 'GTM-PQX5H833'
export const GA_MEASUREMENT_ID = 'G-JRS4P3QC9V'

// Define event types for type safety
export interface AnalyticsEvent {
  event: string
  [key: string]: any
}

// Initialize GTM dataLayer
declare global {
  interface Window {
    dataLayer: any[]
    gtag: (...args: any[]) => void
  }
}

export const initializeAnalytics = () => {
  // Initialize dataLayer
  window.dataLayer = window.dataLayer || []
  
  // GTM initialization
  const gtmScript = document.createElement('script')
  gtmScript.src = `https://www.googletagmanager.com/gtm.js?id=${GTM_ID}`
  gtmScript.async = true
  document.head.appendChild(gtmScript)
  
  // Push GTM initialization
  window.dataLayer.push({
    'gtm.start': new Date().getTime(),
    event: 'gtm.js'
  })
}

// Generic event tracking
export const trackEvent = (eventData: AnalyticsEvent) => {
  if (typeof window !== 'undefined' && window.dataLayer) {
    window.dataLayer.push(eventData)
  }
}

// Page view tracking
export const trackPageView = (url: string, title?: string) => {
  trackEvent({
    event: 'page_view',
    page_location: url,
    page_title: title || document.title,
  })
}

// User authentication events
export const trackAuth = {
  login: (method: string = 'google') => {
    trackEvent({
      event: 'login',
      method,
      timestamp: new Date().toISOString(),
    })
  },
  
  signUp: (method: string = 'google') => {
    trackEvent({
      event: 'sign_up',
      method,
      timestamp: new Date().toISOString(),
    })
  },
  
  logout: () => {
    trackEvent({
      event: 'logout',
      timestamp: new Date().toISOString(),
    })
  }
}

// Book-related events
export const trackBook = {
  create: (templateId?: string) => {
    trackEvent({
      event: 'book_create',
      template_id: templateId,
      timestamp: new Date().toISOString(),
    })
  },
  
  open: (bookId: string) => {
    trackEvent({
      event: 'book_open',
      book_id: bookId,
      timestamp: new Date().toISOString(),
    })
  },
  
  edit: (bookId: string, action: 'file_create' | 'file_edit' | 'file_delete') => {
    trackEvent({
      event: 'book_edit',
      book_id: bookId,
      edit_action: action,
      timestamp: new Date().toISOString(),
    })
  },
  
  delete: (bookId: string) => {
    trackEvent({
      event: 'book_delete',
      book_id: bookId,
      timestamp: new Date().toISOString(),
    })
  }
}

// AI operations tracking
export const trackAI = {
  chatMessage: (bookId: string, messageLength: number, model: string) => {
    trackEvent({
      event: 'ai_chat_message',
      book_id: bookId,
      message_length: messageLength,
      ai_model: model,
      timestamp: new Date().toISOString(),
    })
  },
  
  operation: (operationType: string, bookId: string, success: boolean) => {
    trackEvent({
      event: 'ai_operation',
      operation_type: operationType,
      book_id: bookId,
      success,
      timestamp: new Date().toISOString(),
    })
  },
  
  revert: (operationId: string, bookId: string) => {
    trackEvent({
      event: 'ai_operation_revert',
      operation_id: operationId,
      book_id: bookId,
      timestamp: new Date().toISOString(),
    })
  }
}

// Subscription and billing events
export const trackSubscription = {
  checkoutStart: (planType: string, planPrice: number) => {
    trackEvent({
      event: 'begin_checkout',
      currency: 'USD',
      value: planPrice,
      items: [{
        item_id: planType,
        item_name: `BookWiz ${planType} Plan`,
        category: 'subscription',
        quantity: 1,
        price: planPrice,
      }],
    })
  },
  
  purchase: (planType: string, planPrice: number, transactionId: string) => {
    trackEvent({
      event: 'purchase',
      transaction_id: transactionId,
      currency: 'USD',
      value: planPrice,
      items: [{
        item_id: planType,
        item_name: `BookWiz ${planType} Plan`,
        category: 'subscription',
        quantity: 1,
        price: planPrice,
      }],
    })
  },
  
  cancel: (planType: string) => {
    trackEvent({
      event: 'subscription_cancel',
      plan_type: planType,
      timestamp: new Date().toISOString(),
    })
  },
  
  upgrade: (fromPlan: string, toPlan: string) => {
    trackEvent({
      event: 'subscription_upgrade',
      from_plan: fromPlan,
      to_plan: toPlan,
      timestamp: new Date().toISOString(),
    })
  }
}

// Template usage tracking
export const trackTemplate = {
  view: (templateId: string) => {
    trackEvent({
      event: 'template_view',
      template_id: templateId,
      timestamp: new Date().toISOString(),
    })
  },
  
  use: (templateId: string) => {
    trackEvent({
      event: 'template_use',
      template_id: templateId,
      timestamp: new Date().toISOString(),
    })
  }
}

// Usage and engagement tracking
export const trackUsage = {
  sessionStart: () => {
    trackEvent({
      event: 'session_start',
      timestamp: new Date().toISOString(),
    })
  },
  
  featureUse: (feature: string, context?: string) => {
    trackEvent({
      event: 'feature_use',
      feature_name: feature,
      context,
      timestamp: new Date().toISOString(),
    })
  },
  
  searchQuery: (query: string, resultsCount: number) => {
    trackEvent({
      event: 'search',
      search_term: query,
      results_count: resultsCount,
      timestamp: new Date().toISOString(),
    })
  }
}

// Blog and content engagement
export const trackContent = {
  blogView: (slug: string, title: string) => {
    trackEvent({
      event: 'blog_view',
      blog_slug: slug,
      blog_title: title,
      timestamp: new Date().toISOString(),
    })
  },
  
  blogEngagement: (slug: string, action: 'scroll_50' | 'scroll_90' | 'time_on_page') => {
    trackEvent({
      event: 'blog_engagement',
      blog_slug: slug,
      engagement_type: action,
      timestamp: new Date().toISOString(),
    })
  }
}

// Error tracking
export const trackError = {
  jsError: (error: Error, context?: string) => {
    trackEvent({
      event: 'exception',
      description: error.message,
      fatal: false,
      context,
      timestamp: new Date().toISOString(),
    })
  },
  
  apiError: (endpoint: string, statusCode: number, errorMessage: string) => {
    trackEvent({
      event: 'api_error',
      endpoint,
      status_code: statusCode,
      error_message: errorMessage,
      timestamp: new Date().toISOString(),
    })
  }
}