Skip to main content

Custom Integration - Build Your Own

Integrate Loyalteez with any platform, application, or service that can make HTTP requests.

Universal Integration Formula

1. Configure events in Partner Portal
2. Detect user action (via SDK or API)
3. Make HTTP POST request
4. User gets rewarded

That's it. If your platform can do these 4 things, it can integrate Loyalteez.


Quick Start: Configure Events First

Before integrating, configure your events in the Partner Portal:

  1. Log into Partner Portal
  2. Navigate to Settings → LTZ Distribution → Automation
  3. Configure events with reward amounts, limits, and detection methods
  4. Enable automation to start tracking

Why configure first?

  • Set reward amounts per event
  • Configure rate limits and cooldowns
  • Choose detection methods (automatic vs manual)
  • Map your internal event names

Event Configuration Methods

Loyalteez supports 4 detection methods for tracking events. Choose based on your integration needs:

1. 🌐 URL Pattern Detection

Best for: Page-based conversions (thank you pages, confirmation pages)

How it works: SDK automatically detects when users visit configured URLs

Configuration in Partner Portal:

  • Event → Detection Method → "Success Page Detection"
  • Add URL patterns: /thank-you, /order-confirmation, /signup-complete
  • Add success indicators (optional): .success-message, #confirmation

Example Integration:

<!-- SDK automatically tracks when user visits /thank-you -->
<script src="https://api.loyalteez.app/sdk.js"></script>
<script>
LoyalteezAutomation.init('YOUR_BRAND_ID');
// No additional code needed - automatic detection!
</script>

Use Cases:

  • Order confirmation pages
  • Registration success pages
  • Download completion pages
  • Subscription activation pages

2. 📝 Form Submission Detection

Best for: Form-based actions (newsletter signups, contact forms, lead generation)

How it works: SDK automatically detects form submissions matching configured selectors

Configuration in Partner Portal:

  • Event → Detection Method → "Registration Form" / "Newsletter Form"
  • Add form selectors: #newsletter-form, .signup-form, form[name="contact"]
  • Specify email field name: email (default)
  • Add success indicators (optional): .form-success, .thank-you-message

Example Integration:

<!-- Form automatically tracked -->
<form id="newsletter-form">
<input type="email" name="email" required>
<button type="submit">Subscribe</button>
</form>

<script src="https://api.loyalteez.app/sdk.js"></script>
<script>
LoyalteezAutomation.init('YOUR_BRAND_ID');
// Form submission automatically tracked
</script>

Use Cases:

  • Newsletter subscriptions
  • Contact form submissions
  • Lead generation forms
  • Registration forms
  • Survey completions

3. 🎯 Element Detection (CSS Selector)

Best for: Button clicks, element visibility, custom interactions

How it works: SDK automatically detects clicks or visibility of configured elements

Configuration in Partner Portal:

  • Event → Detection Method → "Element Detection"
  • Add target selectors: .download-button, #signup-complete, .purchase-confirmation
  • Configure trigger: click or visibility

Example Integration:

<!-- Button click automatically tracked -->
<button class="download-button" data-email="[email protected]">
Download PDF
</button>

<script src="https://api.loyalteez.app/sdk.js"></script>
<script>
LoyalteezAutomation.init('YOUR_BRAND_ID');
// Button click automatically tracked
</script>

Use Cases:

  • Download buttons
  • Social share buttons
  • Video play buttons
  • Custom interaction elements

4. 🔗 API Webhook (Manual)

Best for: Backend-triggered events, server-side integrations, third-party services

How it works: Your backend sends events directly to Loyalteez API

Configuration in Partner Portal:

  • Event → Detection Method → "API Integration"
  • No SDK configuration needed
  • Use API endpoint: POST https://api.loyalteez.app/loyalteez-api/manual-event

Example Integration:

import requests

def track_event(email, event_type, metadata=None):
"""Track event via API webhook."""
response = requests.post(
'https://api.loyalteez.app/loyalteez-api/manual-event',
json={
'event': event_type,
'email': email,
'metadata': metadata or {}
}
)
return response.json()

# Usage: Track purchase completion
track_event(
'[email protected]',
'place_order',
{'order_id': '12345', 'amount': 99.99}
)

Use Cases:

  • Payment processing completion
  • CRM integrations
  • Marketing automation platforms
  • Backend-triggered events
  • Third-party service integrations

Event Configuration Options

When configuring events in Partner Portal, you can set:

Reward Amount

  • Default: Set default LTZ reward per event
  • Per-Event Override: Adjust reward amount per event configuration
  • Range: 1 - 10,000+ LTZ

Rate Limiting

  • Max Claims Per User: Maximum times a user can earn this reward

    • 1 = One-time reward (e.g., account creation)
    • 10 = Repeatable up to 10 times (e.g., purchases)
    • 999999 = Unlimited (use with cooldown)
  • Cooldown Hours: Time period before user can earn again

    • 0 = No cooldown
    • 24 = Once per day
    • 168 = Once per week
  • Max Total Claims: Limit total claims across all users (optional)

    • 100 = First 100 users only
    • 1000 = First 1000 users only
    • Unlimited = No global limit

Event Name Mapping

  • Map Internal Names: Map your event names to Loyalteez events
  • Example: newsletter-signupnewsletter_subscribe
  • Use Case: Keep your existing event naming while using Loyalteez events

Integration Patterns by Detection Method

Pattern 1: E-commerce Checkout (URL Pattern)

Scenario: Reward customers after successful purchase

Partner Portal Setup:

  1. Event: "Place Order (Checkout)"
  2. Detection: URL Pattern (/order-confirmation, /thank-you)
  3. Reward: 200 LTZ
  4. Max Claims: 10 per user
  5. Cooldown: 24 hours

Integration:

<!-- Order confirmation page -->
<div class="order-confirmation">
<h1>Thank you for your order!</h1>
<p>Order #12345 confirmed</p>
</div>

<script src="https://api.loyalteez.app/sdk.js"></script>
<script>
LoyalteezAutomation.init('YOUR_BRAND_ID');
// Automatically tracks when user visits /order-confirmation
</script>

Alternative (Backend):

# After payment processing
def complete_order(order):
# Process payment...

# Track event via API
requests.post('https://api.loyalteez.app/loyalteez-api/manual-event', json={
'event': 'place_order',
'email': order.customer_email,
'metadata': {
'order_id': order.id,
'amount': order.total,
'items': order.items_count
}
})

Pattern 2: Newsletter Signup (Form Submission)

Scenario: Reward users for subscribing to newsletter

Partner Portal Setup:

  1. Event: "Subscribe to Newsletter"
  2. Detection: Form Submission (#newsletter-form)
  3. Reward: 50 LTZ
  4. Max Claims: 1 per user
  5. Cooldown: 0 hours

Integration:

<!-- Newsletter signup form -->
<form id="newsletter-form">
<input type="email" name="email" placeholder="Enter your email" required>
<button type="submit">Subscribe</button>
</form>

<script src="https://api.loyalteez.app/sdk.js"></script>
<script>
LoyalteezAutomation.init('YOUR_BRAND_ID');
// Form submission automatically tracked
</script>

With Custom Success Handler:

document.getElementById('newsletter-form').addEventListener('submit', async (e) => {
e.preventDefault();

const email = e.target.email.value;

// Submit to your backend
await fetch('/api/newsletter/subscribe', {
method: 'POST',
body: JSON.stringify({ email })
});

// SDK automatically tracks via form detection
// OR manually track:
LoyalteezAutomation.track('newsletter_subscribe', {
userEmail: email,
metadata: { source: 'homepage' }
});
});

Pattern 3: Download Whitepaper (Element Detection)

Scenario: Reward users for downloading content

Partner Portal Setup:

  1. Event: Custom Event "Download Whitepaper"
  2. Detection: Element Detection (.download-button)
  3. Reward: 100 LTZ
  4. Max Claims: 1 per user
  5. Cooldown: 0 hours

Integration:

<!-- Download button -->
<button class="download-button" data-email="[email protected]">
Download Whitepaper
</button>

<script src="https://api.loyalteez.app/sdk.js"></script>
<script>
LoyalteezAutomation.init('YOUR_BRAND_ID');
// Button click automatically tracked
</script>

With Manual Tracking:

document.querySelector('.download-button').addEventListener('click', async () => {
const email = getUserEmail(); // Your function to get user email

// Trigger download
window.location.href = '/downloads/whitepaper.pdf';

// Track event manually
LoyalteezAutomation.track('custom_YOUR_BRAND_ID_TIMESTAMP', {
userEmail: email,
metadata: {
downloadType: 'whitepaper',
fileName: 'customer-retention-guide.pdf'
}
});
});

Pattern 4: Account Creation (API Webhook)

Scenario: Reward users when account is created in your backend

Partner Portal Setup:

  1. Event: "Create Account / Register"
  2. Detection: API Integration (webhook)
  3. Reward: 100 LTZ
  4. Max Claims: 1 per user
  5. Cooldown: 0 hours

Integration:

# Backend: After user registration
def create_user_account(user_data):
# Create user in your database
user = User.create(
email=user_data['email'],
name=user_data['name']
)

# Track account creation event
track_loyalteez_event(
email=user.email,
event_type='account_creation',
metadata={
'user_id': user.id,
'signup_method': 'email',
'timestamp': datetime.now().isoformat()
}
)

return user

def track_loyalteez_event(email, event_type, metadata):
"""Helper function to track Loyalteez events."""
import requests

response = requests.post(
'https://api.loyalteez.app/loyalteez-api/manual-event',
json={
'event': event_type,
'email': email,
'metadata': metadata
},
timeout=10
)

if response.status_code == 200:
result = response.json()
print(f"✅ User earned {result.get('ltzDistributed', 0)} LTZ")
else:
print(f"⚠️ Event tracking failed: {response.status_code}")

return response.json()

Pattern 5: Referral Program (Hybrid)

Scenario: Reward users for referring friends (form + API)

Partner Portal Setup:

  1. Event: "Refer-a-Friend Program"
  2. Detection: Form Submission + API Integration
  3. Reward: 300 LTZ (referrer) + 100 LTZ (referee)
  4. Max Claims: 10 per user
  5. Cooldown: 24 hours

Integration:

<!-- Referral form -->
<form id="referral-form">
<input type="email" name="referrer_email" value="[email protected]" hidden>
<input type="email" name="friend_email" placeholder="Friend's email" required>
<button type="submit">Send Invite</button>
</form>

<script src="https://api.loyalteez.app/sdk.js"></script>
<script>
LoyalteezAutomation.init('YOUR_BRAND_ID');

// Custom handling for referral
document.getElementById('referral-form').addEventListener('submit', async (e) => {
e.preventDefault();

const referrerEmail = e.target.referrer_email.value;
const friendEmail = e.target.friend_email.value;

// Send referral to your backend
await fetch('/api/referrals/send', {
method: 'POST',
body: JSON.stringify({ referrerEmail, friendEmail })
});

// Track referrer reward
LoyalteezAutomation.track('refer_friend', {
userEmail: referrerEmail,
metadata: { friendEmail }
});
});
</script>

Backend (Reward Referee):

# When friend signs up
def handle_friend_signup(friend_email, referrer_email):
# Create friend's account
friend = create_user_account(friend_email)

# Reward friend for signing up via referral
track_loyalteez_event(
email=friend_email,
event_type='account_creation', # Standard event
metadata={
'referral_source': referrer_email,
'signup_method': 'referral'
}
)

Pattern 6: Event Name Mapping

Scenario: Use your existing event names with Loyalteez events

Partner Portal Setup:

  1. Event: "Subscribe to Newsletter"
  2. Event Name Mapping: newsletter-signupnewsletter_subscribe
  3. Detection: Form Submission or API

Integration:

// Your existing event tracking code
function trackNewsletterSignup(email) {
// Use your internal event name
LoyalteezAutomation.track('newsletter-signup', {
userEmail: email
});

// SDK automatically maps to 'newsletter_subscribe'
// No code changes needed!
}

Backend:

# Your existing backend code
def handle_newsletter_signup(email):
# Use your internal event name
track_event('newsletter-signup', email)

# Automatically mapped to 'newsletter_subscribe' in Partner Portal

Complete Integration Examples

Example 1: Shopify Store Integration

Setup:

  1. Configure "Place Order" event in Partner Portal
  2. Use API webhook method
  3. Set reward: 200 LTZ per order

Integration:

// Shopify webhook handler
app.post('/webhooks/order-created', async (req, res) => {
const order = req.body;

// Track order completion
await fetch('https://api.loyalteez.app/loyalteez-api/manual-event', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
event: 'place_order',
email: order.customer.email,
metadata: {
platform: 'shopify',
order_id: order.id,
order_number: order.order_number,
total: order.total_price,
items: order.line_items.length
}
})
});

res.json({ success: true });
});

Example 2: WordPress Plugin

Setup:

  1. Configure "Post Reviews" event
  2. Use form submission detection
  3. Set reward: 125 LTZ per review

Integration:

<?php
// WordPress plugin
add_action('comment_post', function($comment_ID, $comment_approved) {
if ($comment_approved === 1) {
$comment = get_comment($comment_ID);

// Track review submission
wp_remote_post('https://api.loyalteez.app/loyalteez-api/manual-event', [
'body' => json_encode([
'event' => 'post_review',
'email' => $comment->comment_author_email,
'metadata' => [
'platform' => 'wordpress',
'post_id' => $comment->comment_post_ID,
'comment_id' => $comment_ID,
'comment_length' => strlen($comment->comment_content)
]
]),
'headers' => ['Content-Type' => 'application/json']
]);
}
}, 10, 2);

Example 3: React App with Multiple Events

Setup:

  1. Configure multiple events in Partner Portal
  2. Use SDK for automatic detection
  3. Manual tracking for custom events

Integration:

import { useEffect } from 'react';

function App() {
useEffect(() => {
// Initialize SDK
if (window.LoyalteezAutomation) {
window.LoyalteezAutomation.init('YOUR_BRAND_ID');
}
}, []);

const handleNewsletterSignup = async (email) => {
// Form submission automatically tracked via SDK
// OR manually:
if (window.LoyalteezAutomation) {
window.LoyalteezAutomation.track('newsletter_subscribe', {
userEmail: email,
metadata: { source: 'react_app' }
});
}
};

const handleDownload = async (email, fileName) => {
// Custom event tracking
if (window.LoyalteezAutomation) {
window.LoyalteezAutomation.track('custom_YOUR_BRAND_ID_TIMESTAMP', {
userEmail: email,
metadata: { fileName, type: 'download' }
});
}
};

return (
<div>
{/* Newsletter form - automatically tracked */}
<form id="newsletter-form">
<input type="email" name="email" />
<button type="submit">Subscribe</button>
</form>

{/* Download button - manually tracked */}
<button onClick={() => handleDownload(userEmail, 'guide.pdf')}>
Download Guide
</button>
</div>
);
}

Minimum Requirements

✅ Required

  • Ability to make HTTP POST requests
  • Method to identify users (email, ID, username)
  • Way to detect user actions/events

❌ NOT Required

  • Blockchain knowledge
  • Cryptocurrency experience
  • Smart contract interaction
  • Special SDKs or libraries
  • Privy integration (optional)

Integration Template

Basic HTTP Request

POST https://api.loyalteez.app/loyalteez-api/manual-event
Content-Type: application/json

{
"event": "your_event_name",
"email": "[email protected]",
"metadata": {
"platform": "your_platform",
"any_custom_field": "any_value"
}
}

Response

{
"success": true,
"ltzDistributed": 50,
"transactionHash": "0x...",
"walletAddress": "0x...",
"message": "Event tracked successfully"
}

Platform-Specific Examples

Python (Any Python App)

import requests

def reward_user(user_email, event_type, metadata=None):
"""Track event and reward user with LTZ."""
url = "https://api.loyalteez.app/loyalteez-api/manual-event"

payload = {
"event": event_type,
"email": user_email,
"metadata": metadata or {}
}

try:
response = requests.post(url, json=payload)
data = response.json()

if data.get('success'):
ltz_earned = data.get('ltzDistributed', 0)
print(f"✅ User earned {ltz_earned} LTZ")
return data
else:
print(f"❌ Error: {data.get('message')}")
return None
except Exception as e:
print(f"❌ Request failed: {e}")
return None

# Usage
reward_user(
"[email protected]",
"task_completed",
{"task_id": "123", "difficulty": "hard"}
)

Ruby (Rails, Sinatra)

require 'net/http'
require 'json'

class LoyalteezRewards
API_URL = "https://api.loyalteez.app/loyalteez-api/manual-event"

def self.track_event(email, event, metadata = {})
uri = URI(API_URL)

payload = {
event: event,
email: email,
metadata: metadata
}

response = Net::HTTP.post(
uri,
payload.to_json,
"Content-Type" => "application/json"
)

result = JSON.parse(response.body)

if result['success']
puts "✅ Rewarded user with #{result['ltzDistributed']} LTZ"
result
else
puts "❌ Error: #{result['message']}"
nil
end
rescue => e
puts "❌ Request failed: #{e.message}"
nil
end
end

# Usage
LoyalteezRewards.track_event(
"[email protected]",
"purchase_completed",
{ amount: 99.99, items: 3 }
)

Go (Backend Services)

package main

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)

type EventPayload struct {
Event string `json:"event"`
Email string `json:"email"`
Metadata map[string]interface{} `json:"metadata"`
}

type EventResponse struct {
Success bool `json:"success"`
LtzDistributed int `json:"ltzDistributed"`
TxHash string `json:"transactionHash"`
Wallet string `json:"walletAddress"`
}

func TrackEvent(email, event string, metadata map[string]interface{}) (*EventResponse, error) {
url := "https://api.loyalteez.app/loyalteez-api/manual-event"

payload := EventPayload{
Event: event,
Email: email,
Metadata: metadata,
}

jsonData, err := json.Marshal(payload)
if err != nil {
return nil, err
}

resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
if err != nil {
return nil, err
}
defer resp.Body.Close()

var result EventResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}

if result.Success {
fmt.Printf("✅ User earned %d LTZ\n", result.LtzDistributed)
}

return &result, nil
}

func main() {
metadata := map[string]interface{}{
"action": "api_call",
"endpoint": "/users/create",
}

TrackEvent("[email protected]", "api_usage", metadata)
}

PHP (WordPress, Laravel)

<?php

class LoyalteezRewards {
private const API_URL = 'https://api.loyalteez.app/loyalteez-api/manual-event';

public static function trackEvent($email, $event, $metadata = []) {
$payload = [
'event' => $event,
'email' => $email,
'metadata' => $metadata
];

$ch = curl_init(self::API_URL);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 200) {
$data = json_decode($response, true);

if ($data['success']) {
error_log("✅ User earned {$data['ltzDistributed']} LTZ");
return $data;
}
}

error_log("❌ Failed to track event");
return null;
}
}

// Usage
LoyalteezRewards::trackEvent(
'[email protected]',
'comment_posted',
['post_id' => 123, 'comment_length' => 250]
);

Rust (High-Performance Services)

use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Serialize)]
struct EventPayload {
event: String,
email: String,
metadata: HashMap<String, serde_json::Value>,
}

#[derive(Deserialize)]
struct EventResponse {
success: bool,
#[serde(rename = "ltzDistributed")]
ltz_distributed: Option<i32>,
#[serde(rename = "transactionHash")]
transaction_hash: Option<String>,
}

async fn track_event(
email: &str,
event: &str,
metadata: HashMap<String, serde_json::Value>,
) -> Result<EventResponse, Box<dyn std::error::Error>> {
let client = reqwest::Client::new();
let url = "https://api.loyalteez.app/loyalteez-api/manual-event";

let payload = EventPayload {
event: event.to_string(),
email: email.to_string(),
metadata,
};

let response = client
.post(url)
.json(&payload)
.send()
.await?
.json::<EventResponse>()
.await?;

if response.success {
if let Some(ltz) = response.ltz_distributed {
println!("✅ User earned {} LTZ", ltz);
}
}

Ok(response)
}

#[tokio::main]
async fn main() {
let mut metadata = HashMap::new();
metadata.insert("action".to_string(), serde_json::json!("rust_action"));

track_event("[email protected]", "action_completed", metadata).await.unwrap();
}

User Identification Strategies

Strategy 1: Email-Based (Best)

{
"email": "[email protected]"
}

Pros:

  • ✅ Natural user identifier
  • ✅ Can link to Privy wallets
  • ✅ Human-readable

Strategy 2: Platform ID Mapping

{
"email": "[email protected]"
}

Pros:

  • ✅ Unique per user
  • ✅ Works with any ID system
  • ✅ Same wallet across sessions

Example:

const email = `discord_${userId}@loyalteez.app`;
const email = `telegram_${userId}@loyalteez.app`;
const email = `game_${playerId}@loyalteez.app`;

Strategy 3: Wallet Address

{
"email": "[email protected]"
}

Pros:

  • ✅ For Web3-native platforms
  • ✅ Direct wallet linking

Strategy 4: Hybrid

{
"email": "[email protected]",
"metadata": {
"platform_id": "user_123",
"wallet_address": "0x..."
}
}

Pros:

  • ✅ Multiple identification methods
  • ✅ Flexible linking
  • ✅ Future-proof

Event Design Best Practices

Good Event Names

✅ user_signup
✅ purchase_completed
✅ content_created
✅ milestone_reached
✅ daily_login

Bad Event Names

❌ event
❌ click
❌ action
❌ thing_happened
❌ test

Event Naming Conventions

{category}_{action}
{object}_{verb}
{context}_{event}

Examples:

user_signup
user_login
user_profile_complete

content_created
content_published
content_shared

purchase_completed
purchase_refunded

milestone_100_posts
milestone_1_year

achievement_unlocked
achievement_shared

Metadata Best Practices

Good Metadata

{
"event": "purchase_completed",
"email": "[email protected]",
"metadata": {
"platform": "shopify",
"order_id": "ORD-12345",
"amount": 99.99,
"currency": "USD",
"items_count": 3,
"first_purchase": true,
"timestamp": "2025-11-11T10:00:00Z"
}
}

Minimal Metadata

{
"event": "button_click",
"email": "[email protected]",
"metadata": {
"platform": "web"
}
}

Metadata Fields to Include

Always:

  • platform - Where the event occurred
  • timestamp - When it occurred

Often:

  • user_id - Your internal user ID
  • session_id - Current session
  • source - Traffic source
  • version - App/API version

Context-Specific:

  • amount - For purchases
  • duration - For time-based events
  • level - For games
  • difficulty - For tasks

Error Handling

Python Example

import requests
from requests.exceptions import RequestException

def track_event_with_retry(email, event, metadata, max_retries=3):
"""Track event with automatic retry."""
for attempt in range(max_retries):
try:
response = requests.post(
"https://api.loyalteez.app/loyalteez-api/manual-event",
json={
"event": event,
"email": email,
"metadata": metadata
},
timeout=30
)

if response.status_code == 200:
return response.json()
else:
print(f"⚠️ Attempt {attempt + 1} failed: {response.status_code}")

except RequestException as e:
print(f"⚠️ Attempt {attempt + 1} error: {e}")

if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff

# Queue for later if all retries failed
queue_event(email, event, metadata)
return None

JavaScript Example

async function trackEventWithRetry(email, event, metadata, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(
'https://api.loyalteez.app/loyalteez-api/manual-event',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ event, email, metadata }),
timeout: 30000
}
);

if (response.ok) {
return await response.json();
}

console.warn(`⚠️ Attempt ${attempt + 1} failed: ${response.status}`);
} catch (error) {
console.error(`⚠️ Attempt ${attempt + 1} error:`, error);
}

if (attempt < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, 2 ** attempt * 1000));
}
}

// Queue for later
await queueEvent(email, event, metadata);
return null;
}

Rate Limiting

Client-Side Rate Limiting

class RateLimiter {
constructor(maxRequests, timeWindow) {
this.maxRequests = maxRequests;
this.timeWindow = timeWindow;
this.requests = [];
}

async execute(fn) {
const now = Date.now();

// Remove old requests
this.requests = this.requests.filter(
time => time > now - this.timeWindow
);

if (this.requests.length >= this.maxRequests) {
const waitTime = this.requests[0] - (now - this.timeWindow);
await new Promise(resolve => setTimeout(resolve, waitTime));
return this.execute(fn);
}

this.requests.push(now);
return fn();
}
}

// Usage
const limiter = new RateLimiter(10, 60000); // 10 requests per minute

await limiter.execute(() =>
trackEvent(email, event, metadata)
);

Offline Support

Queue Pattern

// Local queue (browser)
class EventQueue {
constructor() {
this.queue = this.loadQueue();
}

loadQueue() {
const stored = localStorage.getItem('event_queue');
return stored ? JSON.parse(stored) : [];
}

saveQueue() {
localStorage.setItem('event_queue', JSON.stringify(this.queue));
}

add(event) {
this.queue.push({
...event,
queued_at: Date.now()
});
this.saveQueue();
}

async process() {
while (this.queue.length > 0) {
const event = this.queue[0];

try {
await trackEvent(event.email, event.event, event.metadata);
this.queue.shift();
this.saveQueue();
} catch (error) {
console.error('Failed to process queued event:', error);
break; // Stop processing on error
}
}
}
}

// Usage
const queue = new EventQueue();

// When offline
queue.add({ email, event, metadata });

// When back online
await queue.process();

Testing Your Integration

1. Test Event Tracking

curl -X POST https://api.loyalteez.app/loyalteez-api/manual-event \
-H "Content-Type: application/json" \
-d '{
"event": "test_event",
"email": "[email protected]",
"metadata": {
"platform": "test",
"test": true
}
}'

2. Verify in Partner Portal

Go to: https://partners.loyalteez.app/analytics

Check:

  • ✅ Event appears in analytics
  • ✅ User wallet created
  • ✅ LTZ distributed

3. Load Testing

import concurrent.futures
import requests

def send_event(i):
requests.post(
"https://api.loyalteez.app/loyalteez-api/manual-event",
json={
"event": "load_test",
"email": f"user{i}@test.com",
"metadata": {"test_id": i}
}
)
print(f"Sent event {i}")

# Send 100 concurrent requests
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
executor.map(send_event, range(100))

Production Checklist

  • Error handling implemented
  • Retry logic added
  • Rate limiting configured
  • Offline support (if applicable)
  • Logging enabled
  • Analytics monitoring
  • Tested with real users
  • Environment variables set
  • Documented for team

Real-World Examples

Example 1: Wordpress Plugin

Reward blog commenters:

add_action('comment_post', function($comment_ID, $comment_approved) {
if ($comment_approved === 1) {
$comment = get_comment($comment_ID);

LoyalteezRewards::trackEvent(
$comment->comment_author_email,
'blog_comment',
[
'post_id' => $comment->comment_post_ID,
'comment_length' => strlen($comment->comment_content)
]
);
}
}, 10, 2);

Example 2: Minecraft Server Plugin

Reward players for achievements:

@EventHandler
public void onPlayerAchievement(PlayerAchievementAwardedEvent event) {
Player player = event.getPlayer();
String email = player.getUniqueId() + "@minecraft.loyalteez.app";

LoyalteezAPI.trackEvent(
email,
"achievement_unlocked",
Map.of(
"achievement", event.getAchievement().name(),
"player_name", player.getName()
)
);
}

Example 3: Twitch Extension

Reward viewers:

// Twitch Extension backend
app.post('/reward-viewer', async (req, res) => {
const { channelId, viewerId, action } = req.body;

const email = `twitch_${viewerId}@loyalteez.app`;

await trackEvent(email, `twitch_${action}`, {
platform: 'twitch',
channel_id: channelId,
action
});

res.json({ success: true });
});

Configuring Events in Partner Portal

Before integrating, configure your events in the Partner Portal to set reward amounts, limits, and detection methods.

Step-by-Step Configuration

  1. Log into Partner Portal

  2. Add Events

    • Click "Add Event" or "Create Custom Event"
    • Select from predefined events or create custom events
    • Configure detection method (URL Pattern, Form Submission, Element Detection, API Integration)
  3. Set Reward Configuration

    • Reward Amount: LTZ credits per event (e.g., 50, 100, 200)
    • Max Claims Per User: How many times a user can earn (1 = one-time, 10 = repeatable)
    • Cooldown Hours: Time between claims (0 = no cooldown, 24 = once per day)
    • Max Total Claims: Global limit across all users (optional)
  4. Configure Detection Method

    • URL Pattern: Add URL patterns (e.g., /thank-you, /order-confirmation)
    • Form Submission: Add form selectors (e.g., #newsletter-form, .signup-form)
    • Element Detection: Add CSS selectors (e.g., .download-button, #signup-complete)
    • API Integration: No configuration needed - use API endpoint directly
  5. Enable Event

    • Toggle event Enabled switch
    • Event will start tracking immediately (if automation is enabled)
  6. Enable Automation

    • Toggle Automation Enabled switch at the top
    • All enabled events will start tracking

Event Configuration Best Practices

Reward Amounts:

  • Low-value actions (50-100 LTZ): Newsletter signups, downloads, simple engagements
  • Mid-value actions (100-500 LTZ): Account creation, form submissions, demos
  • High-value actions (500-2,000+ LTZ): Purchases, subscriptions, referrals

Rate Limiting:

  • One-time events: Max Claims = 1, Cooldown = 0
  • Repeatable events: Max Claims = 10+, Cooldown = 24 hours
  • Limited campaigns: Max Total Claims = 100 (first 100 users only)

Detection Methods:

  • Use URL Pattern for page-based conversions (easiest, automatic)
  • Use Form Submission for form-based actions (automatic, reliable)
  • Use Element Detection for button clicks (automatic, flexible)
  • Use API Integration for backend events (manual, most control)

Event Name Mapping

Map your internal event names to Loyalteez events without changing your code.

How It Works

  1. In Partner Portal:

    • Edit event configuration
    • Set Event Name Mapping field
    • Example: newsletter-signup → maps to newsletter_subscribe
  2. In Your Code:

    // Use your internal event name
    LoyalteezAutomation.track('newsletter-signup', {
    userEmail: email
    });

    // Automatically mapped to 'newsletter_subscribe'

Use Cases

  • Legacy Systems: Keep existing event names
  • Multiple Integrations: Use different names for same event
  • A/B Testing: Test different event names
  • Migration: Gradually migrate to Loyalteez event names

Testing Your Integration

1. Test Event Configuration

Check Partner Portal:

  • ✅ Events are configured and enabled
  • ✅ Automation is enabled
  • ✅ Detection methods are set correctly
  • ✅ Reward amounts are configured

2. Test Detection Methods

URL Pattern:

# Visit configured URL
curl https://yourwebsite.com/thank-you
# Check browser console for SDK tracking

Form Submission:

<!-- Submit form and check console -->
<form id="newsletter-form">
<input type="email" name="email" value="[email protected]">
<button type="submit">Submit</button>
</form>

Element Detection:

// Click configured element
document.querySelector('.download-button').click();
// Check console for tracking

API Integration:

curl -X POST https://api.loyalteez.app/loyalteez-api/manual-event \
-H "Content-Type: application/json" \
-d '{
"event": "test_event",
"email": "[email protected]",
"metadata": {"test": true}
}'

3. Verify Rewards

Check Analytics:

  • Go to Partner Portal → Analytics
  • Verify events are tracked
  • Check LTZ distribution amounts
  • Verify user wallets are created

Troubleshooting

Events Not Tracking?

Check:

  1. ✅ Automation enabled in Partner Portal?
  2. ✅ Event enabled in configuration?
  3. ✅ Detection method configured correctly?
  4. ✅ SDK loaded and initialized?
  5. ✅ Email provided (if required)?

Debug:

// Enable debug mode
LoyalteezAutomation.init('YOUR_BRAND_ID', { debug: true });

// Check console for:
// - SDK initialization
// - Event detection
// - API requests
// - Error messages

Wrong Reward Amount?

Check:

  1. ✅ Event configuration in Partner Portal
  2. ✅ Reward amount set correctly
  3. ✅ Event name matches (case-sensitive)
  4. ✅ Event name mapping configured (if using)

Rate Limiting Issues?

Check:

  1. ✅ Max Claims Per User setting
  2. ✅ Cooldown Hours setting
  3. ✅ Max Total Claims (if set)
  4. ✅ User's claim history in analytics

Support


Next Steps

  1. Configure events in Partner Portal (Settings → LTZ Distribution → Automation)
  2. Choose detection method (URL Pattern, Form Submission, Element Detection, API)
  3. Set reward amounts and rate limits
  4. Integrate SDK or API in your application
  5. Test integration with test events
  6. Enable automation and launch!

If it can make HTTP requests, it can reward users. 🚀