npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@loyalguru/embed-sdk

v1.0.0

Published

SDK to embed Loyal Guru White Label modules (loyalty, CDP, coupons, login) into external websites and apps using an iframe-based approach.

Readme

WhiteLabel SDK

SDK to embed Loyal Guru White Label modules (loyalty, CDP, coupons, login) into external websites and apps using an iframe-based approach.

This SDK creates and manages an <iframe> that points to your White Label webview (hosted in Loyal Guru infra or in your environment), sends the auth token to it, listens for resize events, and exposes hooks for token refresh and analytics events.

Features

  • Simple initialization using a container div
  • Supports multiple modules: loyalty, cdp, coupons, login
  • Secure token
  • Optional auto-resize (iframe grows/shrinks based on content height)
  • Hooks for:
    • onLoad
    • onError
    • onSize (height/width from iframe)
    • token refresh request (REQUEST_NEW_TOKEN)
  • GTM support via LG_DATALAYER_EVENT (pushes into window.dataLayer)

Installation

1. From source (local development)

git clone https://github.com/loyalguru/WhiteLabel-SDK.git
cd WhiteLabel-SDK
npm install

The project uses Rollup to build a UMD bundle (embed-sdk.umd.js) and TypeScript for typings.

Build

To generate the distributable bundle:

npm run build

This will create the compiled files inside the dist/ folder (according to your current package.json):

  • dist/embed-sdk.umd.js → UMD bundle you can include in a <script>
  • dist/index.d.ts → TypeScript declarations

Publish this to npm/GitHub Packages or serve it from a static/CDN bucket.

Usage

Load the SDK in a plain HTML page and initialize it like this:

<!DOCTYPE html>
<html>
<head>
  <title>Test SDK</title>
  <!-- Load the built SDK (UMD) -->
  <script src="embed-sdk.umd.js"></script>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
  <!-- Container where the iframe will be injected -->
  <div id="loyalty-container"></div>

  <script>
    // Initialize the SDK
    EmbedLoyaltyApp.init({
      containerId: 'loyalty-container',
      module: 'loyalty',              // 'loyalty' | 'cdp' | 'coupons' | 'login'
      iframeOrigin: 'http://localhost:4200', // URL where the white-label modules are hosted
      token: 'YOUR_JWT_TOKEN_HERE',   // JWT generated by your backend
      locale: 'fr',                   // optional, defaults to 'en'
      autoResize: false,              // true: iframe resizes automatically
      onLoad: () => console.log('[host] Iframe loaded'),
      onSize: ({ height }) => console.log('[host] iframe height:', height),
      onError: (err) => console.error('Loyalty iframe error', err)
    });

    // Listen for token refresh requests coming from the iframe
    EmbedLoyaltyApp.onTokenRefreshRequested(async () => {
      // fetch/refresh token from your backend
      const newToken = 'NEW_TOKEN_FROM_BACKEND';
      EmbedLoyaltyApp.refreshToken(newToken);
      console.log('Token refreshed and sent to iframe');
    });

    // Listen to size messages (alternative way)
    EmbedLoyaltyApp.onSizeRequested(({ height, width }) => {
      console.log('[host] SIZE via onSizeRequested =>', height, width);
    });
  </script>
</body>
</html>

API

EmbedLoyaltyApp.init(config: InitConfig)

Creates the iframe and injects it into the container.

Config shape:

type EmbedModule = 'loyalty' | 'cdp' | 'coupons' | 'login';

type InitConfig = {
  containerId: string; // id of the DOM element where the iframe will be appended
  module: EmbedModule; // module to load from the white-label host
  iframeOrigin: string; // e.g. https://wl.loyalguru.com
  token: string;        // JWT to authenticate user/session
  locale?: string;      // optional, defaults to 'en'
  onLoad?: () => void;
  onError?: (e: Error) => void;
  onSize?: (payload: { height: number; width?: number; origin: string }) => void;
  autoResize?: boolean; // if true, SDK updates iframe height on SIZE messages
};

What it does internally:

  1. Finds the container (document.getElementById(...))
  2. Creates an <iframe> pointing to:
    ${iframeOrigin}/${module}
  3. Adds secure-ish sandbox attributes:
    allow-scripts, allow-same-origin, allow-popups, allow-popups-to-escape-sandbox
  4. Sends the auth token to the iframe using postMessage:
    {
      type: 'AUTH_TOKEN',
      token: '...',
      locale: '...'
    }
  5. Listens for messages coming from iframe:
    • REQUEST_NEW_TOKEN
    • LG_DATALAYER_EVENT
    • SIZE

EmbedLoyaltyApp.refreshToken(newToken: string)

Updates the token stored in the SDK and sends it again to the iframe.

Use this when backend issues a new JWT (expiration, refresh flow, etc.):

EmbedLoyaltyApp.refreshToken(freshTokenFromBackend);

EmbedLoyaltyApp.onTokenRefreshRequested(callback: () => void)

The iframe can send a message:

{ "type": "REQUEST_NEW_TOKEN" }

When that happens, the SDK will call to the callback. Call your backend, get a fresh token and call refreshToken(...).

Example:

EmbedLoyaltyApp.onTokenRefreshRequested(async () => {
  const newToken = await fetchNewTokenSomehow();
  EmbedLoyaltyApp.refreshToken(newToken);
});

EmbedLoyaltyApp.onSizeRequested(callback)

Even if autoResize is off, you can still listen to size reports coming from the iframe:

EmbedLoyaltyApp.onSizeRequested(({ height, width, origin }) => {
  console.log('Iframe wants to be', height, 'px high');
});

EmbedLoyaltyApp.destroy()

Removes the iframe from the DOM and clears internal references.

EmbedLoyaltyApp.destroy();

Messages from the iframe

The SDK listens to window.postMessage from the iframe. Current supported messages:

  • REQUEST_NEW_TOKEN -> triggers the registered onTokenRefreshRequested callback.
  • LG_DATALAYER_EVENT -> pushes data.payload into window.dataLayer (for GTM).
  • SIZE{ type: 'SIZE', height: number, width?: number }
    • If autoResize is true, the SDK updates iframe.style.height.
    • Also forwards this to onSize / onSizeRequested.

Styling & Iframe behavior

The iframe is created with these default styles:

Object.assign(this.iframe.style, {
  border: 'none',
  width: '100%',
  height: autoResize ? '0px' : '100vh',
  margin: '0',
  padding: '0',
  display: 'block',
  backgroundColor: 'transparent',
  overflow: 'hidden',
  transition: 'height 0.25s ease',
  'max-height': '100vh'
});

If the parent host page has scroll constraints, you can override these with your own CSS.

Development Notes

  • The SDK currently does not strictly enforce event.origin in the message listener (the line is commented):

    // if (event.origin !== this.origin) return;

    In production should keep origin checks enabled to avoid processing messages from unknown sources.

  • The iframe URL is built as ${iframeOrigin}/${module}. Make sure your white-label host actually serves those routes.

  • If you plan to publish to npm as @loyalguru/embed-sdk, update the repository, name, and CI workflow accordingly.