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
| Attribute | Description | Default |
|---|---|---|
| data-id | Your unique site ID (required) | — |
| data-chat | Enable live chat widget | false |
| data-chat-theme | "dark" or "light" | dark |
| data-chat-position | "bottom-right" or "bottom-left" | bottom-right |
| data-auto-track | Auto-track pageviews | true |
| data-allow-localhost | Enable on localhost | false |
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
| Method | Description |
|---|---|
| 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.config | Object 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