Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mlm-platform.com/llms.txt

Use this file to discover all available pages before exploring further.

Widget Embedding

The MLM Platform provides embeddable widgets for displaying referral information and capturing leads.

Overview

Widgets are embedded using iframes with JWT-based authentication (Widget Access Tokens or WATs).
┌─────────────────────────────────────────┐
│  Your Application                       │
│  ┌───────────────────────────────────┐  │
│  │  iframe (MLM Widget)              │  │
│  │  - Referral link                  │  │
│  │  - Commission stats               │  │
│  │  - Lead capture form              │  │
│  └───────────────────────────────────┘  │
└─────────────────────────────────────────┘

Step 1: Configure Allowed Origins

Before embedding widgets, configure allowed origins in the Admin Dashboard:
  1. Navigate to Settings > Widget Configuration
  2. Add your application’s origin(s):
    • https://yourapp.com
    • https://www.yourapp.com
    • http://localhost:3000 (for development)
  3. Click Save
Only add origins you control. Unauthorized origins will be rejected.

Step 2: Generate a Widget Access Token

Request a WAT from your backend:
// Backend endpoint to generate WAT
app.post('/api/widget-token', async (req, res) => {
  const { userId } = req.body;
  
  const response = await fetch(
    'https://app.mlm-platform.com/api/v1/widget/session',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-tenant-api-key': process.env.MLM_API_KEY
      },
      body: JSON.stringify({ user_id: userId })
    }
  );
  
  const { token, expires_at } = await response.json();
  res.json({ token, expires_at });
});
Response:
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_at": "2024-01-15T11:30:00Z",
  "user_id": "550e8400-e29b-41d4-a716-446655440000"
}

Step 3: Embed the Widget

Use the token to embed the widget iframe:
<iframe
  id="mlm-widget"
  src="https://widget.mlm-platform.example.com/referral?token=YOUR_TOKEN"
  width="400"
  height="300"
  frameborder="0"
  allow="clipboard-write"
></iframe>

React Component

import { useState, useEffect } from 'react';

function ReferralWidget({ userId }) {
  const [token, setToken] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    async function fetchToken() {
      const response = await fetch('/api/widget-token', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ userId })
      });
      const { token } = await response.json();
      setToken(token);
      setLoading(false);
    }
    fetchToken();
  }, [userId]);
  
  if (loading) return <div>Loading widget...</div>;
  
  return (
    <iframe
      src={`https://widget.mlm-platform.example.com/referral?token=${token}`}
      width="400"
      height="300"
      frameBorder="0"
      allow="clipboard-write"
      title="Referral Widget"
    />
  );
}

Widget Types

Displays the user’s referral link with copy functionality:
https://widget.mlm-platform.example.com/referral?token=TOKEN

Commission Stats Widget

Shows commission balance and history:
https://widget.mlm-platform.example.com/stats?token=TOKEN

Lead Capture Widget

Form for capturing leads with referral attribution:
https://widget.mlm-platform.example.com/lead-capture?token=TOKEN

Content Security Policy (CSP)

If your application uses CSP, add the widget domain to frame-src:
Content-Security-Policy: frame-src 'self' https://widget.mlm-platform.example.com;
Or in Next.js middleware:
// middleware.ts
export function middleware(request) {
  const response = NextResponse.next();
  
  response.headers.set(
    'Content-Security-Policy',
    "frame-src 'self' https://widget.mlm-platform.example.com"
  );
  
  return response;
}

Token Refresh

WATs expire after 1 hour. Implement token refresh:
function ReferralWidget({ userId }) {
  const [token, setToken] = useState(null);
  const [expiresAt, setExpiresAt] = useState(null);
  
  async function refreshToken() {
    const response = await fetch('/api/widget-token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ userId })
    });
    const data = await response.json();
    setToken(data.token);
    setExpiresAt(new Date(data.expires_at));
  }
  
  useEffect(() => {
    refreshToken();
    
    // Refresh 5 minutes before expiry
    const interval = setInterval(() => {
      if (expiresAt && new Date() > new Date(expiresAt - 5 * 60 * 1000)) {
        refreshToken();
      }
    }, 60000);
    
    return () => clearInterval(interval);
  }, [userId]);
  
  // ... render iframe
}

Troubleshooting

Widget Not Loading

  1. Check origin configuration: Verify your origin is in the allowed list
  2. Check token: Ensure token is valid and not expired
  3. Check CSP: Verify frame-src allows the widget domain
  4. Check browser console: Look for CORS or CSP errors

CORS Errors

Refused to frame 'https://widget.mlm-platform.example.com/' 
because an ancestor violates the following Content Security Policy directive...
Solution: Add the widget domain to your CSP frame-src directive.

Token Expired

{
  "error": "Token expired",
  "code": "TOKEN_EXPIRED"
}
Solution: Implement token refresh as shown above.

Origin Not Allowed

{
  "error": "Origin not allowed",
  "code": "ORIGIN_NOT_ALLOWED"
}
Solution: Add your origin to the allowed origins list in the Admin Dashboard.