Examples
Coming Soon — Tested examples are being added as we validate real-world integration patterns. The patterns below are conceptual and may require adjustments for your specific use case.
Common patterns for integrating lio-client into your applications.
Monitor Workflow Status
Check if your content sync is healthy:
import { createLioClient } from '@lytics/lio-client';
import { contentstackPlugin } from '@lytics/lio-client-contentstack';
const lio = createLioClient({
apiKey: process.env.LYTICS_API_KEY,
plugins: [contentstackPlugin()]
});
await lio.init();
// Get sync status
const status = await lio.contentstack.getSyncStatus();
if (status.status === 'failed') {
console.error('❌ Sync failed!');
// Send alert to Slack/PagerDuty
} else if (status.status === 'running') {
console.log('🔄 Sync in progress...');
} else {
console.log(`✅ Sync healthy. Last sync: ${status.lastSync}`);
}Enrich CMS Content in Real-Time
Add Lytics data to content as users fetch it:
import contentstack from '@contentstack/delivery-sdk';
import { createLioClient } from '@lytics/lio-client';
import { contentstackPlugin } from '@lytics/lio-client-contentstack';
const cms = contentstack.Stack({
api_key: process.env.CONTENTSTACK_API_KEY,
delivery_token: process.env.CONTENTSTACK_DELIVERY_TOKEN,
environment: 'production'
});
const lio = createLioClient({
apiKey: process.env.LYTICS_API_KEY,
plugins: [contentstackPlugin()]
});
await lio.init();
// Fetch and enrich
const entries = await cms.ContentType('blog_post').Entry.Query().find();
const enriched = await lio.contentstack.enrichMany(entries[0]);
// Now entries have _lytics field
for (const entry of enriched) {
console.log(`${entry.title}:`);
if (entry._lytics) {
console.log(' Topics:', Object.keys(entry._lytics.topics).slice(0, 5).join(', '));
console.log(' Segments:', entry._lytics.segments.length);
}
}Build a Content Performance Dashboard
Query all content and generate analytics:
import { createLioClient } from '@lytics/lio-client';
const lio = createLioClient({
apiKey: process.env.LYTICS_API_KEY
});
await lio.init();
const analytics = {
totalContent: 0,
topTopics: new Map(),
segmentCoverage: new Set()
};
// Scan all content
for await (const batch of lio.content.scan()) {
for (const content of batch) {
analytics.totalContent++;
// Aggregate topics
for (const [topic, score] of Object.entries(content.lytics || {})) {
analytics.topTopics.set(
topic,
(analytics.topTopics.get(topic) || 0) + score
);
}
// Track segment coverage
for (const segment of content._segments || []) {
analytics.segmentCoverage.add(segment);
}
}
}
console.log('📊 Content Analytics:');
console.log(` Total pieces: ${analytics.totalContent}`);
console.log(` Unique segments: ${analytics.segmentCoverage.size}`);
const topTopics = [...analytics.topTopics.entries()]
.sort((a, b) => b[1] - a[1])
.slice(0, 10);
console.log(' Top topics:', topTopics.map(([t]) => t).join(', '));Filter Content with SegmentQL
Query specific content using Lytics SegmentQL:
import { createLioClient } from '@lytics/lio-client';
const lio = createLioClient({
apiKey: process.env.LYTICS_API_KEY
});
await lio.init();
// Find articles from the last 30 days
console.log('📅 Recent articles:');
for await (const batch of lio.content.scan({
filter: 'AND (_created > "now-30d", aspects = "article")',
limit: 50
})) {
for (const article of batch) {
console.log(` - ${article.title} (${article._created})`);
}
}
// Find high-performing content with multiple topics
console.log('\n🔥 High-performing multi-topic content:');
for await (const batch of lio.content.scan({
filter: 'AND (pageviews > 1000, EXISTS lytics.technology, EXISTS lytics.marketing)',
limit: 20
})) {
for (const content of batch) {
const topics = Object.keys(content.lytics || {}).slice(0, 3).join(', ');
console.log(` - ${content.title}: ${topics}`);
}
}
// Use saved segments for complex queries
console.log('\n📊 Content from saved segment:');
for await (const batch of lio.content.scanSegment('high_performing_content')) {
console.log(` Got ${batch.length} high-performing articles`);
for (const article of batch) {
console.log(` - ${article.title} (pageviews: ${article.pageviews})`);
}
}Reuse Business Logic: Use scanSegment() to reference complex SegmentQL queries defined in Lytics UI, keeping your code DRY.
Scheduled Content Audit
Run daily to detect content without enrichment:
import { createLioClient } from '@lytics/lio-client';
import contentstack from '@contentstack/delivery-sdk';
const lio = createLioClient({
apiKey: process.env.LYTICS_API_KEY
});
const cms = contentstack.Stack({
api_key: process.env.CONTENTSTACK_API_KEY,
delivery_token: process.env.CONTENTSTACK_DELIVERY_TOKEN,
environment: 'production'
});
await lio.init();
// Get all CMS entries
const cmsEntries = await cms.ContentType('blog_post').Entry.Query().find();
// Build Lytics content map
const lyticsContent = new Map();
for await (const batch of lio.content.scan()) {
for (const item of batch) {
lyticsContent.set(item.url, item);
}
}
// Find missing enrichment
const missing = [];
for (const entry of cmsEntries[0]) {
if (!lyticsContent.has(entry.url)) {
missing.push(entry);
}
}
if (missing.length > 0) {
console.log(`⚠️ ${missing.length} entries missing Lytics enrichment:`);
for (const entry of missing.slice(0, 10)) {
console.log(` - ${entry.title} (${entry.url})`);
}
// Send report to team
}Serverless Function Integration
Use in AWS Lambda, Cloudflare Workers, or Vercel Functions:
Vercel
// api/enrich.ts
import { createLioClient } from '@lytics/lio-client';
import { contentstackPlugin } from '@lytics/lio-client-contentstack';
import type { VercelRequest, VercelResponse } from '@vercel/node';
const lio = createLioClient({
apiKey: process.env.LYTICS_API_KEY,
plugins: [contentstackPlugin()]
});
export default async function handler(req: VercelRequest, res: VercelResponse) {
await lio.init();
const { url } = req.query;
const content = await lio.content.getByUrl(url as string);
res.status(200).json(content);
}Cold Starts: Consider caching the lio client instance across invocations in long-running serverless environments.
Next.js Server Actions
Use in Next.js App Router:
// app/actions.ts
'use server';
import { createLioClient } from '@lytics/lio-client';
import { contentstackPlugin } from '@lytics/lio-client-contentstack';
const lio = createLioClient({
apiKey: process.env.LYTICS_API_KEY,
plugins: [contentstackPlugin()]
});
export async function getEnrichedContent(url: string) {
await lio.init();
return await lio.content.getByUrl(url);
}
export async function getSyncStatus() {
await lio.init();
return await lio.contentstack.getSyncStatus();
}// app/dashboard/page.tsx
import { getEnrichedContent, getSyncStatus } from '../actions';
export default async function Dashboard() {
const status = await getSyncStatus();
const content = await getEnrichedContent('example.com/blog/post');
return (
<div>
<h1>Sync Status: {status.status}</h1>
<h2>Content Topics:</h2>
<ul>
{Object.keys(content.lytics || {}).map(topic => (
<li key={topic}>{topic}</li>
))}
</ul>
</div>
);
}Error Handling Best Practices
Robust error handling for production:
import { createLioClient } from '@lytics/lio-client';
const lio = createLioClient({
apiKey: process.env.LYTICS_API_KEY
});
await lio.init();
async function safeEnrich(url: string) {
try {
const content = await lio.content.getByUrl(url);
return { success: true, data: content };
} catch (error) {
if (error.status === 404) {
console.log(`Content not found: ${url}`);
return { success: false, error: 'not_found' };
} else if (error.status === 429) {
console.error('Rate limited, retry later');
return { success: false, error: 'rate_limited' };
} else {
console.error('API error:', error.message, error.request_id);
return { success: false, error: 'api_error' };
}
}
}
const result = await safeEnrich('example.com/page');
if (result.success) {
console.log('Enrichment:', result.data);
}TypeScript Integration
Full type safety in your applications:
import {
createLioClient,
type LioClient,
type ContentEntity,
type WorkflowListResponse
} from '@lytics/lio-client';
const lio: LioClient = createLioClient({
apiKey: process.env.LYTICS_API_KEY
});
await lio.init();
// Types inferred automatically
const workflows: WorkflowListResponse = await lio.workflows.list();
const content: ContentEntity = await lio.content.getByUrl('example.com');
// Type-safe plugin usage
import { contentstackPlugin, type EnrichedContentstackEntry } from '@lytics/lio-client-contentstack';
const enriched: EnrichedContentstackEntry<MyEntry> =
await lio.contentstack.enrich(myEntry);Next Steps
- GitHub Repository - View source, report issues
- npm Package - Latest releases
- Lytics API Docs - Full API reference