API Client SDK

TypeScript/JavaScript client for Entrolytics API

API Client SDK

The @entrolytics/api-client package provides a type-safe TypeScript/JavaScript client for interacting with the Entrolytics API. It supports all endpoints including analytics, websites, organizations, links, pixels, boards, and the new Phase 2 features (Web Vitals, Form Analytics, Deployment Tracking).

Installation

pnpm add @entrolytics/api-client

Quick Start

import getClient from '@entrolytics/api-client'

// Initialize client
const client = getClient({
  endpoint: 'https://entrolytics.dev/api',
  apiKey: process.env.ENTROLYTICS_API_KEY,
  // OR use bearer token (Clerk JWT)
  bearerToken: 'your-clerk-jwt-token'
})

// Get your websites
const { ok, data: websites } = await client.getMyWebsites()

// Get website stats
const { data: stats } = await client.getWebsiteStats('website-id', {
  startAt: Date.now() - 7 * 24 * 60 * 60 * 1000, // 7 days ago
  endAt: Date.now(),
  unit: 'day'
})

Configuration

ClientConfig

interface ClientConfig {
  /** API base URL (default: https://entrolytics.dev/api) */
  endpoint?: string
  /** API key for authentication */
  apiKey?: string
  /** Bearer token (Clerk JWT) for authentication */
  bearerToken?: string
}

Authentication

Choose between API key or bearer token authentication:

API Key

const client = getClient({
  apiKey: process.env.ENTROLYTICS_API_KEY
})

Bearer Token (Clerk)

const client = getClient({
  bearerToken: await auth().getToken()
})

API Reference

Me Endpoints

// Get current user
const { data: user } = await client.getMe()

// Get my websites
const { data: websites } = await client.getMyWebsites()

// Get my organizations
const { data: orgs } = await client.getMyOrgs()

// Update password
await client.updateMyPassword({
  currentPassword: 'old',
  newPassword: 'new'
})

Website Endpoints

// List websites
const { data: websites } = await client.getWebsites()

// Get single website
const { data: website } = await client.getWebsite('website-id')

// Create website
const { data: newSite } = await client.createWebsite({
  domain: 'example.com',
  name: 'My Site'
})

// Update website
await client.updateWebsite('website-id', {
  name: 'Updated Name'
})

// Delete website
await client.deleteWebsite('website-id')

// Reset website (clear all data)
await client.resetWebsite('website-id')

// Transfer website to another org
await client.transferWebsite('website-id', { orgId: 'new-org-id' })

// Get website stats
const { data: stats } = await client.getWebsiteStats('website-id', {
  startAt: timestamp,
  endAt: timestamp,
  unit: 'day'
})

// Get pageviews
const { data: pageviews } = await client.getWebsitePageviews('website-id', {
  startAt: timestamp,
  endAt: timestamp,
  unit: 'day'
})

// Get metrics
const { data: metrics } = await client.getWebsiteMetrics('website-id', {
  type: 'url',
  startAt: timestamp,
  endAt: timestamp
})

// Get real-time data
const { data: realtime } = await client.getRealtimeData('website-id')

// Get active visitors
const { data: active } = await client.getWebsiteActive('website-id')

// Export website data
const { data: exportData } = await client.exportWebsiteData('website-id', {
  startAt: timestamp,
  endAt: timestamp,
  format: 'csv'
})

Organization Endpoints

// List organizations
const { data: orgs } = await client.getOrgs()

// Create organization
const { data: org } = await client.createOrg({ name: 'My Org' })

// Get organization
const { data: org } = await client.getOrg('org-id')

// Get organization users
const { data: users } = await client.getOrgUsers('org-id')

// Add user to organization
await client.addOrgUser('org-id', {
  email: 'user@example.com',
  role: 'member'
})

// Get organization websites
const { data: websites } = await client.getOrgWebsites('org-id')

Session Endpoints

// Get website sessions
const { data: sessions } = await client.getWebsiteSessions('website-id', {
  startAt: timestamp,
  endAt: timestamp
})

// Get session details
const { data: session } = await client.getSession('session-id')

// Get session activity (events, pageviews)
const { data: activity } = await client.getSessionActivity('session-id')

// Get weekly traffic patterns
const { data: traffic } = await client.getWeeklyTraffic('website-id')
// List links
const { data: links } = await client.getLinks()

// Get organization links
const { data: orgLinks } = await client.getOrgLinks('org-id')

// Create link
const { data: link } = await client.createLink({
  url: 'https://example.com/product',
  slug: 'summer-sale',
  utmSource: 'twitter',
  utmCampaign: 'summer-2024'
})

// Get link details
const { data: link } = await client.getLink('link-id')

// Update link
await client.updateLink('link-id', { slug: 'new-slug' })

// Delete link
await client.deleteLink('link-id')

Pixel Endpoints

// List pixels
const { data: pixels } = await client.getPixels()

// Get organization pixels
const { data: orgPixels } = await client.getOrgPixels('org-id')

// Create pixel
const { data: pixel } = await client.createPixel({
  name: 'Newsletter Open',
  type: 'email'
})

// Get pixel details
const { data: pixel } = await client.getPixel('pixel-id')

// Delete pixel
await client.deletePixel('pixel-id')

Board Endpoints (Custom Dashboards)

// List boards
const { data: boards } = await client.getBoards()

// Create board
const { data: board } = await client.createBoard({
  name: 'Marketing Dashboard',
  description: 'Custom analytics dashboard'
})

// Get board details
const { data: board } = await client.getBoard('board-id')

// Get board widgets
const { data: widgets } = await client.getBoardWidgets('board-id')

// Create widget
const { data: widget } = await client.createBoardWidget('board-id', {
  type: 'line',
  title: 'Traffic Over Time',
  config: { metrics: ['pageviews', 'visitors'] }
})

// Update widget
await client.updateBoardWidget('board-id', 'widget-id', { title: 'New Title' })

// Delete widget
await client.deleteBoardWidget('board-id', 'widget-id')

Report Endpoints

// List reports
const { data: reports } = await client.getReports('website-id')

// Create report
const { data: report } = await client.createReport('website-id', {
  name: 'Monthly Report',
  type: 'funnel'
})

// Run funnel report
const { data: funnel } = await client.runFunnelReport('website-id', {
  urls: ['/signup', '/onboarding', '/dashboard'],
  startAt: timestamp,
  endAt: timestamp
})

// Run retention report
const { data: retention } = await client.runRetentionReport('website-id', {
  startAt: timestamp,
  endAt: timestamp
})

// Run journey report
const { data: journey } = await client.runJourneyReport('website-id', {
  startAt: timestamp,
  endAt: timestamp
})

// Run revenue report
const { data: revenue } = await client.runRevenueReport('website-id', {
  startAt: timestamp,
  endAt: timestamp
})

// Run UTM report
const { data: utm } = await client.runUTMReport('website-id', {
  startAt: timestamp,
  endAt: timestamp
})

Web Vitals Endpoints (Phase 2)

// Get website Web Vitals summary
const { data: vitals } = await client.getWebsiteVitals('website-id', {
  startAt: timestamp,
  endAt: timestamp
})

// Get individual Web Vital events
const { data: vitalEvents } = await client.getWebsiteVitalEvents('website-id', {
  metric: 'LCP', // LCP, FID, CLS, FCP, TTFB, INP
  startAt: timestamp,
  endAt: timestamp
})

// Track a Web Vital measurement
await client.trackVital('website-id', {
  metric: 'LCP',
  value: 2500,
  rating: 'needs-improvement',
  url: '/dashboard',
  navigationType: 'navigate'
})

// Batch track multiple vitals
await client.trackVitalsBatch('website-id', {
  vitals: [
    { metric: 'LCP', value: 2500, rating: 'needs-improvement' },
    { metric: 'CLS', value: 0.05, rating: 'good' },
    { metric: 'FID', value: 100, rating: 'good' }
  ]
})

Form Analytics Endpoints (Phase 2)

// Get website forms
const { data: forms } = await client.getWebsiteForms('website-id')

// Get form fields analytics
const { data: fields } = await client.getFormFields('website-id', 'form-id')

// Get form events
const { data: events } = await client.getFormEvents('website-id', 'form-id')

// Track form event
await client.trackFormEvent('website-id', {
  formId: 'contact-form',
  eventType: 'submit', // focus, blur, change, submit, abandon
  fieldName: 'email',
  timeSpent: 5000
})

// Batch track form events
await client.trackFormEventsBatch('website-id', {
  events: [
    { formId: 'signup', eventType: 'focus', fieldName: 'name' },
    { formId: 'signup', eventType: 'blur', fieldName: 'name', timeSpent: 2000 }
  ]
})

Deployment Tracking Endpoints (Phase 2)

// Get website deployments
const { data: deployments } = await client.getWebsiteDeployments('website-id')

// Get deployment details
const { data: deployment } = await client.getDeployment(
  'website-id',
  'deploy-id'
)

// Compare recent deployments
const { data: comparison } = await client.compareDeployments('website-id', 10)

// Set deployment (from CI/CD)
await client.setDeployment('website-id', {
  deployId: 'vercel-deploy-abc123',
  source: 'vercel',
  gitBranch: 'main',
  gitSha: 'abc123',
  deployUrl: 'https://example.vercel.app'
})

Error Handling

All methods return an ApiResponse<T> with error handling:

const result = await client.getWebsites()

if (!result.ok) {
  console.error('Error:', result.error)
  console.error('Status:', result.status)
  return
}

// Type-safe data access
const websites = result.data

Response Type

interface ApiResponse<T> {
  ok: boolean
  data?: T
  error?: string
  status?: number
}

Runtime Detection

The client automatically detects your runtime environment:

import {
  detectRuntime,
  isEdgeRuntime,
  isNodeRuntime
} from '@entrolytics/api-client'

// Detect runtime
const runtime = detectRuntime() // 'node' | 'edge' | 'browser'

// Check specific runtime
if (isEdgeRuntime()) {
  // Edge-specific code
}

if (isNodeRuntime()) {
  // Node.js-specific code
}

Edge Helpers

For edge function deployments:

import {
  getGeoFromRequest,
  getClientIp,
  getRegionInfo
} from '@entrolytics/api-client'

// Get geographic info from request headers
const geo = getGeoFromRequest(request)
console.log(geo.country, geo.city, geo.region)

// Get client IP
const ip = getClientIp(request)

// Get region info
const region = getRegionInfo(request)

Features

  • ✅ Type-safe API client with full TypeScript support
  • ✅ Support for both API key and JWT bearer token auth
  • ✅ Comprehensive error handling
  • ✅ Runtime detection (Node.js, Edge, Browser)
  • ✅ Edge helpers for serverless environments
  • ✅ All core endpoints (websites, orgs, sessions, links, pixels, boards)
  • ✅ Phase 2 features (Web Vitals, Form Analytics, Deployments)
  • ✅ Zero dependencies (uses native fetch)
  • ✅ Works in Node.js, Edge, and browsers

Examples

Build a Custom Dashboard

import getClient from '@entrolytics/api-client'

async function getDashboardData(websiteId: string) {
  const client = getClient({
    apiKey: process.env.ENTROLYTICS_API_KEY
  })

  const now = Date.now()
  const weekAgo = now - 7 * 24 * 60 * 60 * 1000

  const [stats, pageviews, topPages, vitals] = await Promise.all([
    client.getWebsiteStats(websiteId, {
      startAt: weekAgo,
      endAt: now,
      unit: 'day'
    }),
    client.getWebsitePageviews(websiteId, {
      startAt: weekAgo,
      endAt: now,
      unit: 'day'
    }),
    client.getWebsiteMetrics(websiteId, {
      type: 'url',
      startAt: weekAgo,
      endAt: now
    }),
    client.getWebsiteVitals(websiteId, {
      startAt: weekAgo,
      endAt: now
    })
  ])

  return {
    stats: stats.data,
    pageviews: pageviews.data,
    topPages: topPages.data,
    webVitals: vitals.data
  }
}

Server-Side Analytics Export

import getClient from '@entrolytics/api-client'
import { writeFileSync } from 'fs'

async function exportAnalytics() {
  const client = getClient({
    apiKey: process.env.ENTROLYTICS_API_KEY
  })

  const { data: websites } = await client.getWebsites()

  for (const site of websites || []) {
    const { data: stats } = await client.getWebsiteStats(site.id, {
      startAt: Date.now() - 30 * 24 * 60 * 60 * 1000,
      endAt: Date.now(),
      unit: 'day'
    })

    writeFileSync(`export-${site.domain}.json`, JSON.stringify(stats, null, 2))
  }
}

Track Deployments in CI/CD

import getClient from '@entrolytics/api-client'

// In your CI/CD pipeline
async function trackDeployment() {
  const client = getClient({
    apiKey: process.env.ENTROLYTICS_API_KEY
  })

  await client.setDeployment(process.env.WEBSITE_ID, {
    deploymentId: process.env.VERCEL_DEPLOYMENT_ID,
    provider: 'vercel',
    branch: process.env.VERCEL_GIT_COMMIT_REF,
    commit: process.env.VERCEL_GIT_COMMIT_SHA,
    message: process.env.VERCEL_GIT_COMMIT_MESSAGE
  })
}

Support