Bodygram

Integration Guide

Step-by-step integration for plain HTML, React, Vue, and common patterns.

Step-by-Step Integration

1. Load the SDK

The SDK is a browser script that must be loaded before calling new Body2FitSDK(...). For plain HTML, add it to your <head>:

<script src="https://v3.body2fit.bodygram.com/sdk.js"></script>

For React and Vue, see Framework Integration below.

2. Initialize the widget

Create an instance with your configuration. See Configuration for all available options.

const widget = new Body2FitSDK({
  clientKey: 'YOUR_CLIENT_KEY',
  countryCode: 'US',
  languageCode: 'en',
  brandId: 'YOUR_BRAND_ID',
  garmentSKU: 'YOUR_GARMENT_SKU',
  preferredMeasurementSystem: 'metric',
});

3. Embed the widget

Call widget.embed() to insert the widget iframe into the DOM (hidden until opened).

widget.embed();

4. Handle the size recommendation

Listen for the recommendation event to receive the size the widget recommends. The callback receives the raw { type, payload } message the widget posts — read the size from data.payload. See the event reference for the full payload.

widget.on('recommendation', (data) => {
  const { recommendedSize } = data.payload.recommendation;
  console.log('Recommended size:', recommendedSize);
  // Use recommendedSize to pre-select the size on your product page
});

5. Handle widget close

Optionally listen for the close event to react when the user dismisses the widget.

widget.on('close', () => {
  console.log('Widget closed');
});

6. Open the widget on user action

Wait for the ready event before calling widget.open() — this ensures the widget has finished loading.

widget.on('ready', () => {
  document.getElementById('find-my-size').addEventListener('click', () => {
    widget.open();
  });
});

Complete Example

A full plain HTML integration combining all the steps above:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Product Page</title>
    <script src="https://v3.body2fit.bodygram.com/sdk.js"></script>
  </head>
  <body>
    <button id="find-my-size">Find My Size</button>

    <script>
      const widget = new Body2FitSDK({
        clientKey: 'YOUR_CLIENT_KEY',
        countryCode: 'US',
        languageCode: 'en',
        brandId: 'YOUR_BRAND_ID',
        garmentSKU: 'YOUR_GARMENT_SKU',
        preferredMeasurementSystem: 'metric',
      });

      widget.embed();

      widget.on('ready', () => {
        document.getElementById('find-my-size').addEventListener('click', () => {
          widget.open();
        });
      });

      widget.on('recommendation', (data) => {
        console.log('Recommended size:', data.payload.recommendation.recommendedSize);
        // Pre-select the size in your product page UI
      });

      widget.on('close', () => {
        console.log('Widget dismissed');
      });
    </script>
  </body>
</html>

Framework Integration

For React and Vue, load the SDK dynamically when the component mounts.

React

import { useEffect, useRef } from 'react';

declare global {
  interface Window {
    Body2FitSDK: any;
  }
}

function SizeFinder() {
  const widgetRef = useRef<any>(null);

  useEffect(() => {
    const script = document.createElement('script');
    script.src = 'https://v3.body2fit.bodygram.com/sdk.js';
    script.async = true;

    script.onload = () => {
      widgetRef.current = new window.Body2FitSDK({
        clientKey: 'YOUR_CLIENT_KEY',
        countryCode: 'US',
        languageCode: 'en',
        brandId: 'YOUR_BRAND_ID',
        garmentSKU: 'YOUR_GARMENT_SKU',
        preferredMeasurementSystem: 'metric',
      });
      widgetRef.current.embed();
    };

    document.head.appendChild(script);

    return () => {
      widgetRef.current?.destroy();
      document.head.removeChild(script);
    };
  }, []);

  return <button onClick={() => widgetRef.current?.open()}>Find My Size</button>;
}

export default SizeFinder;

The cleanup function calls destroy() when the component unmounts to remove the widget and its event listeners.

Vue

<template>
  <button @click="widget?.open()">Find My Size</button>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';

const widget = ref<any>(null);

onMounted(() => {
  const script = document.createElement('script');
  script.src = 'https://v3.body2fit.bodygram.com/sdk.js';
  script.async = true;

  script.onload = () => {
    widget.value = new (window as any).Body2FitSDK({
      clientKey: 'YOUR_CLIENT_KEY',
      countryCode: 'US',
      languageCode: 'en',
      brandId: 'YOUR_BRAND_ID',
      garmentSKU: 'YOUR_GARMENT_SKU',
      preferredMeasurementSystem: 'metric',
    });
    widget.value.embed();
  };

  document.head.appendChild(script);
});

onUnmounted(() => {
  widget.value?.destroy();
});
</script>

Widget Lifecycle

The widget progresses through these states during a session. Understanding the lifecycle helps you know when to perform setup, respond to user actions, and clean up.

StepDescriptionEvent
Initializenew Body2FitSDK(config) called.—
Embedembed() called; widget iframe added to DOM (hidden).—
ReadyWidget loaded and ready. Safe to call open().ready
OpenWidget is visible to the user.—
Size recommendedWidget computed a recommendation and showed the result screen.recommendation
CloseUser dismisses the widget.close
Destroydestroy() called; widget removed from DOM.—
widget.on('ready', () => {
  // Safe to call widget.open() here
});

widget.on('recommendation', (data) => {
  // data.payload.recommendation.recommendedSize — e.g. "M", "L", "32"
  // data.payload.recommendation.goodFit — whether it's considered a good fit
  // data.payload.profile — the profile the recommendation was computed for
});

See API Reference for full event payload definitions.


Best Practices

Initialize once per page load. The SDK manages its own internal state. Don't create multiple instances for the same garment on the same page.

Destroy when unmounting. Call widget.destroy() when removing the widget from the DOM — especially in single-page applications. This prevents memory leaks and removes event listeners.

Wait for ready before opening programmatically. If you need to open the widget without a user gesture, listen for the ready event before calling widget.open().

Keep garmentSKU in sync with the displayed product. On multi-variant product pages, re-initialize the SDK with the correct garmentSKU when the user switches variants.


Common Patterns

These examples show typical ways to extend the basic integration for common use cases.

E-Commerce Cart Integration

Pre-select the recommended size in your size picker when the widget produces a recommendation.

widget.on('recommendation', (data) => {
  const { recommendedSize } = data.payload.recommendation;
  const sizeSelector = document.querySelector('select[name="size"]');
  if (sizeSelector) {
    sizeSelector.value = recommendedSize;
    sizeSelector.dispatchEvent(new Event('change'));
  }
});

The widget does not add anything to your cart itself — it reports the recommended size and leaves the cart interaction to your own page.

Custom Trigger Button

Open and close the widget programmatically using your own buttons or triggers. Always wait for ready before attaching open/close controls.

widget.embed();

widget.on('ready', () => {
  document.getElementById('open-widget').addEventListener('click', () => {
    widget.open();
  });

  document.getElementById('close-widget').addEventListener('click', () => {
    widget.close();
  });
});

Conditionally Show the Size Guide Button

Call the static isProductSupported() method to show the size guide button only when the current product is supported by Body2Fit. Because it's static, you can check before creating the widget instance.

const config = {
  clientKey: 'YOUR_CLIENT_KEY',
  countryCode: 'US',
  languageCode: 'en',
  brandId: 'YOUR_BRAND_ID',
  garmentSKU: 'YOUR_GARMENT_SKU',
  preferredMeasurementSystem: 'metric',
};

const supported = await Body2FitSDK.isProductSupported(config);

const btn = document.getElementById('size-guide-btn');
if (btn) {
  btn.style.display = supported ? 'block' : 'none';
}

Custom Styling

Override the default look using the theme configuration option. Each key is converted from camelCase to a kebab-case CSS custom property (e.g. primaryForeground → --primary-foreground) and the widget uses the same CSS variable system as Tailwind CSS theme variables. See Configuration → Theme for the full structure.

const widget = new Body2FitSDK({
  clientKey: 'YOUR_CLIENT_KEY',
  countryCode: 'US',
  languageCode: 'en',
  brandId: 'YOUR_BRAND_ID',
  garmentSKU: 'YOUR_GARMENT_SKU',
  preferredMeasurementSystem: 'metric',
  theme: {
    primary: 'oklch(0.4127 0.0935 257.5)',
    primaryForeground: 'oklch(0.98 0 0)',
  },
});

On this page