SDK Reference

Web Integration

Complete reference for the Phi SDK. Analytics, duration tracking, chat, and user identification.

Installation

Add to your website's <head> section:

HTML
<script src="https://phi.llc/phi.js" data-id="your-site-id"></script>

Add data-chat="true" to enable the chat widget.

Configuration

AttributeDescriptionDefault
data-idYour unique site ID (required)
data-chatEnable live chat widgetfalse
data-chat-theme"dark" or "light"dark
data-chat-position"bottom-right" or "bottom-left"bottom-right
data-auto-trackAuto-track pageviewstrue
data-allow-localhostEnable on localhostfalse

Automatic Tracking

The SDK automatically tracks the following without any code:

  • Pageviews — Every page load and SPA navigation
  • Duration — Active time on page (pauses when tab hidden)
  • Device — Browser, OS, screen size, device type
  • Location — Country and city from IP
  • Referrer — Traffic source and UTM parameters
  • Session — Unique session and visitor IDs

Duration Tracking

Time-on-page is tracked automatically using the Visibility API. This ensures accurate engagement metrics:

  • • Only counts time when the tab is visible and active
  • • Pauses automatically when user switches tabs
  • • Sends duration on page exit via sendBeacon
  • • Works with SPAs (sends duration before navigation)
  • • Capped at 30 minutes to ignore idle sessions

Duration appears in the Event Stream with format like "2m 30s" or "45s".

Custom Events

Track user actions beyond pageviews:

JavaScript
// Track a button click
phi.track('ButtonClicked', { button: 'signup' });

// Track a purchase
phi.track('Purchase', {
  value: 99.99,
  currency: 'USD',
  productId: 'prod_123'
});

// Track a form submission
phi.track('FormSubmitted', { form: 'contact' });

User Identification

Link anonymous visitors to known users after login:

JavaScript
// After user logs in
phi.identify('user@example.com', {
  name: 'John Doe',
  marketing_consent: true
});

// Check if already identified
const email = phi.getIdentifiedEmail();
if (email) {
  console.log('User:', email);
}

Once identified, the user's email appears in the Event Stream instead of "Anonymous". See User Identification for details.

Chat API

Control the chat widget programmatically:

JavaScript
// Open/close/toggle chat
phi.chat.open();
phi.chat.close();
phi.chat.toggle();

// Pre-fill user info (before they open chat)
phi.chat.setUser({
  name: 'John Doe',
  email: 'john@example.com'
});
HTML
<!-- Open chat on button click -->
<button onclick="phi.chat.open()">
  💬 Chat with us
</button>

API Reference

MethodDescription
phi.track(event, data)Track a custom event with optional metadata
phi.identify(email, traits)Link visitor to email address
phi.getIdentifiedEmail()Get previously identified email (or null)
phi.chat.open()Open the chat widget
phi.chat.close()Close the chat widget
phi.chat.toggle()Toggle chat open/closed
phi.chat.setUser(user)Pre-fill user info for chat
phi.configObject with siteId, visitorId, sessionId

Next.js / React

TSX
// pages/_app.tsx or app/layout.tsx
import Script from 'next/script';

export default function App({ Component, pageProps }) {
  return (
    <>
      <Script
        src="https://phi.llc/phi.js"
        data-id="your-site-id"
        data-chat="true"
        strategy="afterInteractive"
      />
      <Component {...pageProps} />
    </>
  );
}
TypeScript
// Type declarations (optional)
declare global {
  interface Window {
    phi: {
      track: (event: string, data?: Record<string, any>) => void;
      identify: (email: string, traits?: Record<string, any>) => Promise<boolean>;
      getIdentifiedEmail: () => string | null;
      chat: {
        open: () => void;
        close: () => void;
        toggle: () => void;
        setUser: (user: { name?: string; email?: string }) => void;
      };
      config: {
        siteId: string;
        visitorId: string;
        sessionId: string;
        chatEnabled: boolean;
      };
    };
  }
}

Best Practices

  • Place script in <head> for early loading
  • Call phi.identify() after login for attribution
  • Track meaningful events (purchases, signups) not every click
  • Use PascalCase for event names (e.g., UserSignup)
  • Use data-allow-localhost="true" for local testing