Documentation Index
Fetch the complete documentation index at: https://docs.loyalty.lt/llms.txt
Use this file to discover all available pages before exploring further.
Examples
Complete working examples demonstrating various SDK features.
Live Examples
The SDK includes several HTML examples you can run locally:
| Example | Description | File |
|---|
| QR Login | Customer authentication via QR | examples/qr-login-example.html |
| QR Card Scan | POS customer identification | examples/qr-card-scan-example.html |
| Full POS System | Complete POS simulation | examples/pos-full-example.html |
Running Examples
# Clone the repository
git clone https://github.com/Loyalty-lt/sdk-javascript.git
cd sdk-javascript
# Install dependencies & build
yarn install
yarn build
# Open examples in browser
open examples/qr-login-example.html
POS System Example
A complete Point of Sale implementation with customer identification, cart management, and points processing.
Features
- Split-screen layout (Customer Display + POS Interface)
- QR code customer identification
- Real-time Ably updates
- Product catalog
- Cart with points earning preview
- Points redemption
- Manual card lookup
- Send app download link
Key Code
import { LoyaltySDK } from '@loyaltylt/sdk';
class POSSystem {
private sdk: LoyaltySDK;
private currentCustomer: Customer | null = null;
private cart: CartItem[] = [];
constructor(apiKey: string, apiSecret: string) {
this.sdk = new LoyaltySDK({
apiKey,
apiSecret,
environment: 'production'
});
}
// Start customer identification
async startIdentification() {
const session = await this.sdk.generateQrCardSession('POS');
this.displayQR(session.qr_code);
// Get Ably options with automatic token renewal
const ablyOptions = await this.sdk.createAblyClientOptions(session.session_id);
const tokenResponse = await this.sdk.getAblyToken(session.session_id);
// Connect to Ably (token auto-renews)
const ably = new Ably.Realtime(ablyOptions);
const channel = ably.channels.get(tokenResponse.channel);
channel.subscribe('card_identified', (message) => {
this.handleCustomerIdentified(message.data.card_data);
});
}
// Process checkout
async checkout() {
const total = this.calculateTotal();
const pointsToEarn = Math.floor(total * 10);
await this.sdk.createTransaction({
card_id: this.currentCustomer.cardId,
amount: total,
points: pointsToEarn,
type: 'earn',
description: 'Purchase',
reference: `POS-${Date.now()}`
});
this.showSuccess(`+${pointsToEarn} points earned!`);
this.clearCart();
this.clearCustomer();
}
}
Points Calculation
Use the SDK’s built-in calculation functions for accurate points math:
import {
calculateAmountFromPoints,
calculatePointsFromAmount,
calculateFinalAmount
} from '@loyaltylt/sdk';
// Points rules from card_identified event
const pointsRules = cardData.redemption;
// Calculate discount value
const discount = calculateAmountFromPoints(500, pointsRules);
// 500 points = 5.00 EUR
// Calculate points to earn
const pointsToEarn = calculatePointsFromAmount(cartTotal, pointsRules);
// 25.00 EUR = 250 points
// Calculate final amount after discount
const finalAmount = calculateFinalAmount(cartTotal, pointsToRedeem, pointsRules);
// 50.00 EUR - 5.00 EUR = 45.00 EUR
Always use the pointsRules from the backend instead of hardcoding values.
Rules can vary per partner and may change.
React Integration
Next.js App Router
// app/loyalty/page.tsx
'use client';
import { useState, useEffect } from 'react';
import { QRLogin, QRCardDisplay } from '@loyaltylt/sdk/react';
import '@loyaltylt/sdk/styles';
export default function LoyaltyPage() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [userToken, setUserToken] = useState<string | null>(null);
useEffect(() => {
const token = localStorage.getItem('loyalty_token');
if (token) {
setUserToken(token);
setIsLoggedIn(true);
}
}, []);
if (!isLoggedIn) {
return (
<div className="flex min-h-screen items-center justify-center">
<QRLogin
apiKey={process.env.NEXT_PUBLIC_LOYALTY_API_KEY!}
apiSecret={process.env.NEXT_PUBLIC_LOYALTY_API_SECRET!}
onAuthenticated={(user, token) => {
localStorage.setItem('loyalty_token', token);
setUserToken(token);
setIsLoggedIn(true);
}}
/>
</div>
);
}
return (
<div className="container mx-auto p-8">
<h1 className="text-2xl font-bold mb-6">Your Loyalty Card</h1>
<QRCardDisplay
apiKey={process.env.NEXT_PUBLIC_LOYALTY_API_KEY!}
apiSecret={process.env.NEXT_PUBLIC_LOYALTY_API_SECRET!}
userToken={userToken!}
showPoints
showUserInfo
/>
</div>
);
}
Environment Variables
# .env.local
NEXT_PUBLIC_LOYALTY_API_KEY=lty_your_api_key
NEXT_PUBLIC_LOYALTY_API_SECRET=your_api_secret
Node.js Backend
Express.js Integration
// server.ts
import express from 'express';
import { LoyaltySDK } from '@loyaltylt/sdk';
const app = express();
app.use(express.json());
const sdk = new LoyaltySDK({
apiKey: process.env.LOYALTY_API_KEY!,
apiSecret: process.env.LOYALTY_API_SECRET!,
environment: 'production'
});
// Award points after purchase
app.post('/api/orders/complete', async (req, res) => {
const { orderId, cardNumber, amount } = req.body;
try {
// Find customer's card
const cards = await sdk.getLoyaltyCards({ card_number: cardNumber });
if (!cards.data.length) {
return res.status(404).json({ error: 'Card not found' });
}
const card = cards.data[0];
const pointsToAward = Math.floor(amount * 10);
// Award points
const transaction = await sdk.createTransaction({
card_id: card.id,
amount,
points: pointsToAward,
type: 'earn',
description: `Order #${orderId}`,
reference: orderId
});
res.json({
success: true,
points_awarded: pointsToAward,
new_balance: card.points_balance + pointsToAward
});
} catch (error) {
console.error('Error awarding points:', error);
res.status(500).json({ error: 'Failed to award points' });
}
});
// Get customer info by card number
app.get('/api/customers/lookup', async (req, res) => {
const { card_number } = req.query;
try {
const cards = await sdk.getLoyaltyCards({ card_number: String(card_number) });
if (!cards.data.length) {
return res.status(404).json({ error: 'Card not found' });
}
const card = cards.data[0];
res.json({
name: card.user?.name,
card_number: card.card_number,
points: card.points_balance,
status: card.status
});
} catch (error) {
res.status(500).json({ error: 'Lookup failed' });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Webhooks Integration
// Handle loyalty webhooks
app.post('/api/webhooks/loyalty', async (req, res) => {
const { event, data } = req.body;
switch (event) {
case 'points.awarded':
console.log(`Customer ${data.customer_id} earned ${data.points} points`);
// Update your database, send notification, etc.
break;
case 'points.redeemed':
console.log(`Customer ${data.customer_id} redeemed ${data.points} points`);
break;
case 'offer.claimed':
console.log(`Customer claimed offer: ${data.offer_id}`);
break;
}
res.json({ received: true });
});
GitHub Repository
All examples are available in the SDK repository:
GitHub Repository
View complete source code and examples
Next Steps
API Reference
Complete SDK API documentation
Shop API Docs
Backend API documentation