s-m-r-t

@happyvertical/smrt-analytics

Server-side analytics tracking with GA4 and Plausible integration, event logging, scheduled reports, and AI-powered performance analysis.

v0.19.0GA4PlausibleAI Insights

Overview

smrt-analytics provides server-side analytics event tracking, property/data stream management, scheduled reporting, and AI-powered performance analysis for GA4 and Plausible.

Installation

bash
npm install @happyvertical/smrt-analytics

Quick Start

typescript
import {
  AnalyticsPropertyCollection,
  AnalyticsDataStreamCollection,
  AnalyticsEventCollection
} from '@happyvertical/smrt-analytics';

// Initialize
const properties = await AnalyticsPropertyCollection.create({ db: {...} });
const streams = await AnalyticsDataStreamCollection.create({ db: {...} });
const events = await AnalyticsEventCollection.create({ db: {...} });

// Create GA4 property
const property = await properties.create({
  name: 'My Website',
  providerType: 'GA4',
  measurementId: 'G-XXXXXXXXXX',
  apiSecret: 'your-api-secret'
});
await property.save();

// Create web data stream
const stream = await streams.create({
  propertyId: property.id,
  type: 'WEB_DATA_STREAM',
  name: 'Web Stream',
  measurementId: 'G-XXXXXXXXXX'
});
await stream.save();

// Track event
const event = await events.create({
  propertyId: property.id,
  eventName: 'page_view',
  clientId: 'client-123',
  userId: 'user-456',
  params: {
    page_location: 'https://example.com/products',
    page_title: 'Products'
  },
  eventTimestamp: new Date()
});
await event.save();

// Send to GA4
await event.markSent();

Core Models

AnalyticsProperty

typescript
class AnalyticsProperty extends SmrtObject {
  name: string
  providerType: 'GA4' | 'PLAUSIBLE'
  measurementId?: string      // GA4
  apiSecret?: string          // GA4 (encrypted)
  siteDomain?: string         // Plausible
  lastSyncAt?: Date

  async analyzePerformance(): Promise<string>  // AI
  async isPerformingWell(): Promise<boolean>   // AI
}

AnalyticsEvent

typescript
class AnalyticsEvent extends SmrtObject {
  propertyId: string
  eventName: string           // 'page_view', 'purchase', 'sign_up', etc.
  clientId: string            // Anonymous client identifier
  userId?: string             // Authenticated user
  params: Record<string, any> // Event parameters
  eventTimestamp: Date
  status: 'PENDING' | 'SENT' | 'FAILED'
  retryCount: number
  lastAttemptAt?: Date
  errorMessage?: string

  isPageview(): boolean
  isConversion(): boolean
  async markSent(): Promise<void>
  async markFailed(error: string): Promise<void>
  shouldRetry(): boolean
  toTrackEvent(): TrackEvent   // Convert to SDK format
}

AnalyticsReport

typescript
class AnalyticsReport extends SmrtObject {
  propertyId: string
  name: string
  dimensions: string[]        // ['country', 'deviceCategory']
  metrics: string[]           // ['activeUsers', 'sessions']
  dateRange: string           // 'last7Days', 'last30Days', 'custom'
  filters?: Record<string, any>
  frequency: 'ONCE' | 'DAILY' | 'WEEKLY' | 'MONTHLY'
  status: 'DRAFT' | 'SCHEDULED' | 'RUNNING' | 'COMPLETED' | 'FAILED'
  resultData?: any[]          // Cached results
  rowCount?: number
  lastRunAt?: Date

  isDue(): boolean
  calculateNextRun(): Date | null
  async analyzeResults(): Promise<string>    // AI
  async hasPositiveTrends(): Promise<boolean> // AI
}

Event Tracking

typescript
// Track page view
const pageView = await events.create({
  propertyId: property.id,
  eventName: 'page_view',
  clientId: req.cookies.clientId,
  userId: req.user?.id,
  params: {
    page_location: req.url,
    page_title: 'Product Page',
    page_referrer: req.headers.referer
  },
  eventTimestamp: new Date()
});
await pageView.save();

// Track purchase
const purchase = await events.create({
  propertyId: property.id,
  eventName: 'purchase',
  clientId: req.cookies.clientId,
  userId: req.user.id,
  params: {
    transaction_id: order.id,
    value: order.total,
    currency: 'USD',
    items: order.items.map(item => ({
      item_id: item.productId,
      item_name: item.name,
      quantity: item.quantity,
      price: item.price
    }))
  },
  eventTimestamp: new Date()
});
await purchase.save();

// Get stats
const stats = await events.getPropertyStats(property.id);
console.log(`Total: ${stats.total}, Sent: ${stats.sent}`);

Scheduled Reports

typescript
// Create weekly report
const report = await reports.create({
  propertyId: property.id,
  name: 'Weekly Traffic Report',
  dimensions: ['country', 'deviceCategory', 'date'],
  metrics: ['activeUsers', 'sessions', 'bounceRate'],
  dateRange: 'last7Days',
  frequency: 'WEEKLY',
  status: 'SCHEDULED'
});
await report.save();

// Check if due
if (report.isDue()) {
  report.status = 'RUNNING';
  await report.save();

  // Run report (integrate with SDK)
  const results = await runAnalyticsReport(report);

  report.resultData = results;
  report.rowCount = results.length;
  report.lastRunAt = new Date();
  report.status = 'COMPLETED';
  await report.save();

  // AI analysis
  const insights = await report.analyzeResults();
  console.log(insights);
}

AI-Powered Analysis

typescript
// Analyze property performance
const analysis = await property.analyzePerformance();
// "Traffic up 15% this week. Top sources: organic search (45%),
//  direct (30%). Mobile usage increased to 68%."

const isHealthy = await property.isPerformingWell();
// true if metrics trending positively

// Analyze report trends
const reportInsights = await report.analyzeResults();
// "US traffic grew 20%, UK declined 5%. Mobile bounce rate
//  improved from 65% to 58%."

const hasGrowth = await report.hasPositiveTrends();
// true if key metrics improving

Best Practices

Related Modules