JavaScript SDK
The @graph8/js SDK gives you typed access to every graph8 capability from any JavaScript or TypeScript project. 14 modules, one g8.init() call.
Installation
npm install @graph8/jsAuth Modes
The SDK has two auth modes depending on what you’re building:
| Mode | Key | Use case | Safe in browser? |
|---|---|---|---|
| Client-side | writeKey | Tracking, visitor ID, copilot, chat, calendar, forms | Yes |
| Server-side | apiKey | Enrichment, sequences, campaigns, integrations, voice, pages | No |
// Client-side (browser)g8.init({ writeKey: 'YOUR_WRITE_KEY' });
// Server-side (Node.js)g8.init({ apiKey: 'YOUR_API_KEY' });
// Both (full access)g8.init({ writeKey: 'YOUR_WRITE_KEY', apiKey: 'YOUR_API_KEY' });Quick Start
import { g8 } from '@graph8/js';
g8.init({ writeKey: 'YOUR_WRITE_KEY' });
// Track eventsg8.track('signup', { plan: 'pro', source: 'landing_page' });
// Identify usersg8.identify('user@acme.com', { name: 'Jane Smith', company: 'Acme Corp', job_title: 'VP Engineering',});
// Know who's visitingconst visitor = await g8.visitors.identify();// { company_name: 'Acme Corp', industry: 'SaaS', employee_count: '200-500' }
// Open AI copilotg8.copilot.open({ greeting: 'How can I help?' });
// Show booking widgetg8.calendar.show({ username: 'thomas', eventType: 'demo-30min' });React / Next.js
import { G8Provider } from '@graph8/js/react';
export default function RootLayout({ children }) { return ( <G8Provider writeKey="YOUR_WRITE_KEY"> {children} </G8Provider> );}// Any componentimport { useG8 } from '@graph8/js/react';
function PricingPage() { const { track, visitors, copilot, calendar } = useG8();
useEffect(() => { visitors.identify().then(v => { if (v.company_name) setCompany(v.company_name); }); }, []);
return ( <button onClick={() => { track('book_demo', { page: 'pricing' }); calendar.show({ username: 'thomas', eventType: 'demo' }); }}> Book a Demo </button> );}The hook returns: track, identify, page, reset, visitors, copilot, chat, calendar, forms, signals, and g8 (the full client).
Visitor Intelligence
Identify anonymous visitors by IP address - know which company is on your site before they fill out a form.
// Resolve visitor's companyconst visitor = await g8.visitors.identify();// {// company_name: 'Acme Corp',// company_domain: 'acme.com',// industry: 'SaaS',// employee_count: '200-500',// city: 'San Francisco',// country: 'United States',// confidence: 0.92// }
// Get engagement scoreconst score = await g8.visitors.score();// { engagement: 82, intent: 'high', signals: ['pricing_page', 'case_study'] }
// React to high-intent visitors in real-timeconst stop = g8.visitors.onIntent('high', (visitor) => { showBanner(`${visitor.company_name} is checking us out!`); g8.copilot.open(); // proactively open copilot});
// Stop listeningstop();AI Copilot
Embed an AI assistant in your product that knows your org’s knowledge base.
// Open as a floating widgetg8.copilot.open({ greeting: 'Hi! How can I help you today?', position: 'bottom-right', // or 'bottom-left' theme: 'dark', // 'light', 'dark', or 'auto'});
// Send a message programmaticallyconst answer = await g8.copilot.ask('What integrations do you support?');
// Register custom actions the AI can triggerg8.copilot.registerAction('book_demo', async (params) => { router.push(`/book?date=${params.date}`);});
// Listen for eventsg8.copilot.on('tool_used', (data) => { analytics.track('copilot_action', data);});
// Closeg8.copilot.close();Webchat
Live chat + AI chat embedded in your product.
// Open chat widgetg8.chat.open({ position: 'bottom-right', theme: 'auto', greeting: 'Hi! Ask me anything.',});
// Send a messageg8.chat.send('I need help with billing');
// Listen for eventsg8.chat.on('message', (msg) => { /* new message from agent */ });g8.chat.on('human_transfer', () => { /* transferred to human */ });
// Configure appearanceg8.chat.configure({ position: 'bottom-left', avatar: '/logo.png',});
// Closeg8.chat.close();Calendar Booking
Embed scheduling directly in your product - no Calendly redirect.
// Show as a modal overlayg8.calendar.show({ username: 'thomas', eventType: 'demo-30min', prefill: { name: 'Jane', email: 'jane@acme.com' },});
// Embed inline in a containerg8.calendar.embed('#booking-container', { username: 'thomas', eventType: 'discovery-call',});
// Get available slots programmaticallyconst slots = await g8.calendar.slots('thomas', 'demo-30min', { start: '2026-04-07', end: '2026-04-11',});
// Book programmaticallyconst booking = await g8.calendar.book({ event_type_id: 123, slot: '2026-04-08T10:00:00Z', attendee: { name: 'Jane', email: 'jane@acme.com' },});
// Listen for bookingsg8.calendar.on('booked', (booking) => { showConfirmation(booking);});Progressive Forms
Smart forms that skip fields graph8 already knows - higher conversion, same data.
// Check what's already knownconst result = await g8.forms.lookup('user@acme.com');
if (result.found) { console.log('Known:', result.known_fields); // { name: 'Jane Smith', company: 'Acme Corp' }
console.log('Still need:', result.missing_fields); // ['phone', 'job_title']}Enrichment
// Initialize with API keyg8.init({ apiKey: 'YOUR_API_KEY' });
// Look up a person (1 credit)const person = await g8.enrich.person({ email: 'jane@acme.com' });// { found: true, confidence: 0.95, data: { name, title, company, phone, linkedin, ... } }
// Look up a company (1 credit)const company = await g8.enrich.company({ domain: 'acme.com' });// { found: true, data: { name, industry, revenue, headcount, tech_stack, ... } }
// Verify an email (1 credit)const result = await g8.enrich.verifyEmail('jane@acme.com');// { email: 'jane@acme.com', valid: true, deliverable: true, catch_all: false }
// Search 300M+ contacts with filtersconst leads = await g8.enrich.search([ { field: 'seniority_level', operator: 'any_of', value: ['VP', 'Director'] }, { field: 'company_industry', operator: 'contains', value: ['SaaS'] }, { field: 'company_employee_count', operator: 'between', value: [50, 500] },], 1, 25);Intent Signals
Know when target accounts are in-market.
// Get signals for a specific companyconst signals = await g8.signals.company('acme.com');// { domain: 'acme.com', score: 87, intent: 'high', signals: ['pricing_3x', 'case_study'] }
// Stream signals for multiple domains (polls every 30s)const stop = g8.signals.stream(['acme.com', 'startup.io'], (signals) => { const hot = signals.filter(s => s.intent === 'high'); if (hot.length > 0) notifySDR(hot);});
// Stop streamingstop();Sequences
// List available sequencesconst sequences = await g8.sequences.list();
// Add contacts to a sequenceawait g8.sequences.add({ sequenceId: sequences[0].id, contactIds: [5028106, 5028105], listId: 637,});Campaigns
// List campaignsconst campaigns = await g8.campaigns.list();
// Create a campaignconst campaign = await g8.campaigns.create({ name: 'Q2 Enterprise Push', category: 'Outbound', target_persona: 'VP Engineering at SaaS 200-1000',});
// Launchawait g8.campaigns.launch(campaign.id);
// Get statsconst stats = await g8.campaigns.stats(campaign.id);// { sent: 500, opened: 230, replied: 45, meetings: 12 }CRM Integrations
// List connected CRMsconst integrations = await g8.integrations.list();
// Connect a new CRMawait g8.integrations.connect('hubspot', { apiKey: '...' });
// Trigger syncawait g8.integrations.sync('hubspot', { direction: 'bidirectional' });Analytics
const overview = await g8.analytics.overview({ period: '30d' });// { visitors: 12500, contacts_created: 340, emails_sent: 2100, replies: 89, meetings_booked: 23 }Voice AI
// Start an AI voice callconst session = await g8.voice.start({ agent: 'sales-discovery', contactId: 123,});
// Get call analysis after completionconst analysis = await g8.voice.analysis(session.id);// { sentiment: 'positive', summary: '...', next_steps: [...], objections: [...] }Landing Pages
// Clone from any URLconst page = await g8.pages.clone('https://competitor.com/pricing');
// Create from templateconst page = await g8.pages.create({ template: 'lead_magnet', title: 'The Future of Sales',});
// Publish to CDNconst { url } = await g8.pages.publish(page.id);// https://g8-lp-abc12345.pages.devWebhooks
Listen for events from graph8 (server-side).
g8.webhooks.on('reply_received', (event) => { slack.send(`${event.contact} replied to ${event.sequence}`);});
g8.webhooks.on('meeting_booked', (event) => { crm.updateDeal(event.dealId, { stage: 'meeting' });});
// Stop all listenersg8.webhooks.stop();Available events: reply_received, meeting_booked, contact_enriched, contact_created, sequence_completed, campaign_launched, form_submitted, visitor_identified
Privacy
g8.init({ writeKey: 'YOUR_WRITE_KEY', privacy: { dontSend: true, // Disable all cookies and event sending dontStoreUserIds: true, // Don't store user identifiers ipPolicy: 'remove', // 'keep' | 'stripLastOctet' | 'remove' },});SSR Support
All methods are no-ops on the server and execute on the client after hydration. Safe in Next.js, Nuxt, Remix, and any SSR framework.
Config Options
| Option | Type | Default | Description |
|---|---|---|---|
writeKey | string | - | Write key for client-side features |
apiKey | string | - | API key for server-side features |
host | string | https://t.graph8.com | Tracking host URL |
apiUrl | string | https://be.graph8.com | Backend API URL |
debug | boolean | false | Enable debug logging |
privacy.dontSend | boolean | false | Disable cookies and event sending |
privacy.dontStoreUserIds | boolean | false | Don’t store user identifiers |
privacy.ipPolicy | string | keep | keep, stripLastOctet, or remove |
Get Your Keys
- Go to graph8 Settings > MCP & API
- Write key is in the tracking snippet section (client-side)
- API key is in the API tab (server-side)