Embeddable Storefront
API Reference

API Reference

Technical documentation for the TimberCloud Embeddable Storefront, including the embed script, integration script, URL parameters, and PostMessage API.

Embed Script (embed.js)

The embed script provides the simplest integration method, automatically creating and configuring the iframe.

Usage

<div id="timbercloud-embed"></div>
<script
  src="https://embed.timbercloud.com/embed.js"
  data-company="your-company-slug"
  data-theme="light"
  data-width="100%"
  data-height="800px"
  defer
></script>

Attributes

AttributeRequiredDefaultDescription
data-company✅ YesYour TimberCloud company slug
data-themeNolightTheme: light or dark
data-widthNo100%Width of the embed (CSS value)
data-heightNo800pxHeight of the embed (CSS value)

What It Does

The embed.js script automatically:

  1. Creates the iframe inside the #timbercloud-embed container
  2. Sets the return URL to the current page (for password reset)
  3. Handles password reset routing when timbercloud_route and code params are present
  4. Listens for URL changes (popstate) for SPA support
  5. Handles resize messages from the embed
  6. Cleans URL parameters after password reset completion

How It Works

// The embed.js script performs these operations:
 
// 1. Reads configuration from script attributes
const companySlug = script.getAttribute('data-company');
const theme = script.getAttribute('data-theme') || 'light';
const width = script.getAttribute('data-width') || '100%';
const height = script.getAttribute('data-height') || '800px';
 
// 2. Builds the iframe URL with proper parameters
let iframeUrl = `${baseUrl}/${companySlug}`;
 
// 3. Checks for password reset parameters
const urlParams = new URLSearchParams(window.location.search);
const timbercloudRoute = urlParams.get('timbercloud_route');
const resetCode = urlParams.get('code');
 
if (timbercloudRoute) {
  // Password reset scenario
  iframeUrl += `?timbercloud_route=${timbercloudRoute}&code=${resetCode}`;
} else {
  // Normal scenario - add return URL
  iframeUrl += `?timbercloud_return_url=${encodeURIComponent(currentPageUrl)}`;
}
 
// 4. Creates and configures the iframe
const iframe = document.createElement('iframe');
iframe.src = iframeUrl;
iframe.style.width = width;
iframe.style.height = height;
// ... additional configuration
 
// 5. Adds event listeners for URL changes and messages

Message Handling

The embed script listens for these PostMessage types:

Message TypeDescription
timbercloud:resizeResize the iframe to specified height
timbercloud:clean-urlRemove routing params from URL after password reset

Integration Script (timbercloud-integration.js)

For iframe-based integrations, the integration script provides similar automatic functionality.

Usage

<iframe
  id="timbercloud-embed"
  src="https://embed.timbercloud.com/your-company-slug"
  width="100%"
  height="800"
  style="border: none;"
  allow="payment"
></iframe>
 
<script src="https://embed.timbercloud.com/timbercloud-integration.js"></script>

What It Does

The integration script automatically:

  1. Detects TimberCloud iframes on the page
  2. Appends the return URL to iframe src if not present
  3. Handles password reset routing from email links
  4. Sanitizes sensitive parameters from return URLs
  5. Observes DOM changes for dynamically added iframes

Triggering Re-initialization (SPAs)

For single-page applications, trigger re-initialization after navigation:

window.dispatchEvent(new Event('timbercloud:reinit'));

The script also listens to popstate events automatically.

Sensitive Parameter Sanitization

The integration script removes these parameters from return URLs:

  • code
  • token
  • reset_code
  • auth
  • auth_token
  • access_token
  • refresh_token
  • otp
  • verification_code

URL Parameters

The embed accepts the following URL parameters:

timbercloud_return_url

Specifies the URL to return to after actions like password reset.

<iframe
  src="https://embed.timbercloud.com/your-company-slug?timbercloud_return_url=https://yoursite.com/shop"
  ...
></iframe>

Manual usage:

const currentPageUrl = window.location.href;
const embedUrl = `https://embed.timbercloud.com/your-company-slug?timbercloud_return_url=${encodeURIComponent(currentPageUrl)}`;
document.getElementById('timbercloud-embed').src = embedUrl;

timbercloud_route

Navigates to a specific internal route within the embed.

<!-- Open directly to login page -->
<iframe
  src="https://embed.timbercloud.com/your-company-slug?timbercloud_route=/auth/login"
  ...
></iframe>

Available routes:

RouteDescription
/Product catalog (home)
/auth/loginLogin page
/auth/registerRegistration page
/auth/forgot-passwordPassword reset request
/auth/reset-passwordPassword reset form (requires code)
/checkoutCheckout page
/ordersOrder history
/orders/[id]Specific order details
/accountAccount settings
/account/payment-methodsManage payment methods
/account/settingsAccount settings
/product/[id]Product detail page

code

Used for password reset tokens. Automatically included in password reset email links.

<iframe
  src="https://embed.timbercloud.com/your-company-slug?timbercloud_route=/auth/reset-password&code=RESET_TOKEN"
  ...
></iframe>

PostMessage Communication

The embed supports bidirectional communication via the browser's postMessage API.

Messages FROM the Embed

Message TypeDataDescription
timbercloud-request-url{ type: 'timbercloud-request-url' }Embed requests current URL
timbercloud:resize{ type: 'timbercloud:resize', height: number }Request iframe resize
timbercloud:clean-url{ type: 'timbercloud:clean-url', action: 'remove-params' }Clean URL params

Messages TO the Embed

Message TypeDataDescription
timbercloud-config{ type: 'timbercloud-config', config: { returnUrl: string } }Send configuration

Handling URL Requests (Manual Integration)

window.addEventListener('message', function(event) {
  // Security: verify the origin
  if (event.origin !== 'https://embed.timbercloud.com') return;
  
  // Check if embed is requesting URL
  if (event.data && event.data.type === 'timbercloud-request-url') {
    const iframe = document.getElementById('timbercloud-embed');
    
    iframe.contentWindow.postMessage({
      type: 'timbercloud-config',
      config: {
        returnUrl: window.location.href
      }
    }, 'https://embed.timbercloud.com');
  }
});

Password Reset Flow

Flow Diagram

┌─────────────────────────────────────────────────────────────────┐
│ 1. User clicks "Forgot Password" in embed                       │
│    └─> Enters email address                                     │
├─────────────────────────────────────────────────────────────────┤
│ 2. TimberCloud sends password reset email with link:            │
│    https://yoursite.com/shop?timbercloud_route=/auth/           │
│    reset-password&code=RESET_TOKEN                              │
├─────────────────────────────────────────────────────────────────┤
│ 3. User clicks link → Returns to your site                      │
│    └─> Embed script detects the parameters                      │
├─────────────────────────────────────────────────────────────────┤
│ 4. Script passes routing params to iframe                       │
│    └─> Embed navigates to password reset form                   │
├─────────────────────────────────────────────────────────────────┤
│ 5. User enters new password → Stays on your site                │
│    └─> Script cleans URL parameters                             │
└─────────────────────────────────────────────────────────────────┘

Complete Examples

Example 1: Script Embed (Recommended)

<!DOCTYPE html>
<html>
<head>
  <title>Shop | Your Site</title>
  <link rel="preconnect" href="https://embed.timbercloud.com">
</head>
<body>
  <h1>Our Store</h1>
  
  <div id="timbercloud-embed"></div>
  
  <script
    src="https://embed.timbercloud.com/embed.js"
    data-company="your-company-slug"
    data-theme="light"
    data-width="100%"
    data-height="900px"
    defer
  ></script>
</body>
</html>

Example 2: Iframe with Integration Script

<!DOCTYPE html>
<html>
<head>
  <title>Shop | Your Site</title>
  <link rel="preconnect" href="https://embed.timbercloud.com">
</head>
<body>
  <h1>Our Store</h1>
  
  <div style="
    position: relative;
    left: 50%;
    right: 50%;
    margin-left: -50vw;
    margin-right: -50vw;
    width: 100vw;
    max-width: 100vw;
    overflow: hidden;
    padding: 0 16px;
  ">
    <iframe
      id="timbercloud-embed"
      src="https://embed.timbercloud.com/your-company-slug"
      width="100%"
      height="1280"
      style="border: none; border-radius: 8px; display: block;"
      title="Product Catalog"
      allow="payment"
    ></iframe>
  </div>
 
  <script src="https://embed.timbercloud.com/timbercloud-integration.js"></script>
</body>
</html>

Example 3: Manual Integration (No Scripts)

<!DOCTYPE html>
<html>
<head>
  <title>Shop | Your Site</title>
</head>
<body>
  <h1>Our Store</h1>
  
  <iframe
    id="timbercloud-embed"
    width="100%"
    height="800"
    style="border: none;"
    allow="payment"
  ></iframe>
 
  <script>
    const COMPANY_SLUG = 'your-company-slug';
    const EMBED_URL = 'https://embed.timbercloud.com';
    
    function initEmbed() {
      const iframe = document.getElementById('timbercloud-embed');
      const urlParams = new URLSearchParams(window.location.search);
      const timbercloudRoute = urlParams.get('timbercloud_route');
      const resetCode = urlParams.get('code');
      
      let embedUrl;
      if (timbercloudRoute) {
        embedUrl = `${EMBED_URL}/${COMPANY_SLUG}?timbercloud_route=${encodeURIComponent(timbercloudRoute)}`;
        if (resetCode) {
          embedUrl += `&code=${encodeURIComponent(resetCode)}`;
        }
      } else {
        embedUrl = `${EMBED_URL}/${COMPANY_SLUG}?timbercloud_return_url=${encodeURIComponent(window.location.href)}`;
      }
      
      iframe.src = embedUrl;
    }
    
    window.addEventListener('message', function(event) {
      if (event.origin !== 'https://embed.timbercloud.com') return;
      
      if (event.data?.type === 'timbercloud-request-url') {
        document.getElementById('timbercloud-embed').contentWindow.postMessage({
          type: 'timbercloud-config',
          config: { returnUrl: window.location.href }
        }, 'https://embed.timbercloud.com');
      }
      
      if (event.data?.type === 'timbercloud:clean-url') {
        const url = new URL(window.location.href);
        url.searchParams.delete('timbercloud_route');
        url.searchParams.delete('code');
        window.history.replaceState({}, document.title, url.toString());
      }
    });
    
    document.addEventListener('DOMContentLoaded', initEmbed);
    window.addEventListener('popstate', initEmbed);
  </script>
</body>
</html>

Example 4: React Component

import { useEffect, useRef } from 'react';
 
export function TimberCloudEmbed({ 
  companySlug, 
  theme = 'light', 
  height = '800px' 
}) {
  const containerRef = useRef(null);
 
  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;
 
    // Create placeholder div
    const embedDiv = document.createElement('div');
    embedDiv.id = 'timbercloud-embed';
    container.appendChild(embedDiv);
 
    // Load embed script
    const script = document.createElement('script');
    script.src = 'https://embed.timbercloud.com/embed.js';
    script.setAttribute('data-company', companySlug);
    script.setAttribute('data-theme', theme);
    script.setAttribute('data-width', '100%');
    script.setAttribute('data-height', height);
    script.defer = true;
    container.appendChild(script);
 
    return () => {
      container.innerHTML = '';
    };
  }, [companySlug, theme, height]);
 
  return <div ref={containerRef} />;
}
 
// Usage
<TimberCloudEmbed 
  companySlug="your-company-slug" 
  theme="light" 
  height="900px" 
/>

Backend API

The embed communicates with your TimberCloud backend automatically. Key endpoints:

EndpointPurpose
GET /api/companies?filters[slug]=...Load company data
GET /api/productsFetch products
GET /api/categoriesFetch categories
POST /api/ordersCreate orders
POST /api/auth/localUser login
POST /api/auth/local/registerUser registration
POST /api/auth/forgot-passwordRequest password reset
POST /api/auth/reset-passwordComplete password reset
GET /api/customer-ordersFetch customer's orders

These API calls are handled internally — you don't need to implement them.


Real-Time Updates

The embed uses Socket.io for real-time data synchronization:

  • Order updates: Automatically refreshes when orders change
  • Product updates: Real-time product data sync
  • Payment updates: Live payment status updates

Socket connection is automatic and requires no configuration.


Security Considerations

Origin Verification

When using PostMessage manually, always verify origins:

window.addEventListener('message', function(event) {
  if (event.origin !== 'https://embed.timbercloud.com') return;
  // Process message...
});

HTTPS Required

All communication occurs over HTTPS. The embed will not function properly on HTTP sites.


Troubleshooting

Embed not loading

  • Verify company slug is correct
  • For Script Embed: ensure <div id="timbercloud-embed"> comes immediately before the script
  • Check browser console for errors
  • Ensure HTTPS is used

Password reset not working

  • Use Script Embed or Iframe + integration script
  • Check console for "TimberCloud:" log messages
  • Ensure URL parameters aren't stripped by your server

Script Embed: Container not found

  • The <div id="timbercloud-embed"> must be the immediate previous sibling of the script
  • Ensure the div exists before the script runs (use defer attribute)