Détail du package

@adalong/widget

adalongcorp1kMIT7.3.11

AdAlong widget library

readme

AdAlong Widget library

Table of contents

Getting Started

You can retrieve a widget api key by creating a widget through our interface : https://app.adalong.com/

Method 1: Via CDN

Quickest way to add the widget to your website : Add the CDN url directly in your HTML code to make it available globally. Ensure to replace [VERSION] with the right version.

  <div id="adalong-widget"></div>

  <script defer src="https://cdn.jsdelivr.net/npm/@adalong/widget@[VERSION]/dist/adalongWidget.js"></script>
  <script>
    window.addEventListener('load', async () => {
        const { initializeAdalongWidget } = window.AdalongWidget;
        const widget = await initializeAdalongWidget({
          token: 'WIDGET_API_KEY'
        });

        await widget.load('#adalong-widget');
    });
    </script>

Method 2: Via NPM

Browser compatibility

This package doesn't support internet explorer.

Install & import the AdAlong Widget package

For projects using npm/webpack:

Install the plugin with NPM : npm install @adalong/widget

Then you can import it in your code :

import AdalongWidget from '@adalong/widget';

// Initialize the widget
const adalongWidget = await AdalongWidget.initializeAdalongWidget({
  token: 'WIDGET_API_KEY',
  config: {
    id: 'customId', // Optional unique identifier
    // Additional configuration options...
  },
});

// Load into DOM element
await adalongWidget.load('#adalong-widget');

Global access

Once instantiated, all widgets in the page can also be retrieved using the global object window.adalongWidgetAPI.

Examples :

// subscribe on events for all widgets
window.adalongWidgetAPI.widgets.forEach((widget) => widget.onEvent(...))

// find a particular widget from another script in the page
const myWidget = window.adalongWidgetAPI.widgets.find(w => w.id === 'customId');

Basic Configuration

The widget accepts configuration options during initialization:

const adalongWidget = await AdalongWidget.initializeAdalongWidget({
  token: 'WIDGET_API_KEY',
  config: {
    id: 'uniqueId', // Unique identifier for this widget instance
    classPrefix: 'custom-', // CSS class prefix (default: 'adl-wdgt-')
  },
});

Data Attributes

You can define two different types of media sources: collections & products.

  • Add the data-products attribute to load the media linked to the provided products.
  • Add the data-collections attribute to load the media linked to the provided collections.

Those values must be an array of strings referring to respectively the product references and the collection ids.

⚠️ In case you don't specify any data-* attributes, the media would come from the fallback sources defined in the widget configuration on app.adalong.com

You can override those media sources using data attributes on your widget container:

<div
  id='adalong-widget'
  data-products='["PRODUCT_REF1", "PRODUCT_REF2"]' // Load specific products
  data-collections='["COLLECTION_ID1"]' // Load specific collections
></div>

Product localization

If you ingested an international catalog, a localization can be set via the AdAlong widget customization interface. This will be the default location for displaying product names, links and pricing information in shop the look. You can override this setting by passing a new location directly as a parameter when the widget is loaded.

adalongWidget.load('#widget', { localization: 'GB' });

⚠️ Please note that the localization names must match those defined during implementation (if in doubt, the list can be viewed via the customization interface).

Events

You can also subscribe to events :

adalongWidget.onEvent('postOpened', (event) => {
  console.log(event.post);
  console.log(event.product);
  console.log(event.position);
  console.log(event.direction);
  console.log(event.elapsedSeconds);
});

For example, this would be the type of information you could receive from an event about a post :

export interface IMedia {
  id: string;
  type: 'image' | 'video' | 'text';
  caption: string;
  source: 'instagram' | 'tiktok';
  username?: string;
  post: string;
  image?: string;
  video?: string;
  thumbnail?: string;
  products?: IProduct[];
  // local properties set by the browser
  postIndex: number;
}

Available events are 'widgetLoaded', 'widgetLoadingFailed', 'thumbnailLoaded', 'thumbnailUnavailable', 'thumbnailHover', 'thumbnailClicked', 'originalPostOpened', 'socialProfileOpened','postOpened', 'postClosed', 'postNavigation', 'videoPlayed', 'carouselArrowClicked', 'carouselNativeScroll', 'shopThisLook', 'packshotClicked', 'minContentNotReached', 'minContentReached', 'widgetViewed'

For more details about events, please refer to the EventMap interface in ./src/types.ts

A custom event is also emitted when a new widget instance is created in the page.

document.addEventListener('adalongWidgetCreated', ({ detail }) => {
  console.log(detail.widget.id);
  // Note that at this point the widget instance should not be loaded yet but
  // you can now wait for the widgetLoaded event or check if the loaded property is true
  if (!detail.widget.loaded) {
    detail.widget.onEvent('widgetLoaded', () => {});
  }
});

Widget Customization & Settings

You can now fully customize the widget according to your needs. This includes :

  • Partial customization :

    • Arrow design and visibility (mobile & desktop mode),
    • All customization available through the AdAlong interface. Those settings & more are also documented as typescript interface in src/types.ts.
  • Global customization :

    • Controlling the carousel layout : Control the carousel (the media list) to slide back and forth between medias thanks to a public function.
    • Controlling the post viewer : Control the postviewer (the view modal) to slide back and forth between medias thanks to a public function.

All custom settings can be passed during instantiation to override the default settings :

await adalongWidget.load('#widget', {
  ...customSettings,
});

Resizing the Widget

You can control the size of the widget by simply applying standard CSS width properties to the widget container element. For example:

<!-- Adjust widget size using inline styles -->
<div id="adalong-widget" style="width: 80%; margin: 0 auto;"></div>

Or using CSS :

/* Make widget responsive but not full width */
#adalong-widget {
  width: 80%;
  max-width: 1200px;
  margin: 0 auto;
}

/* Adjust widget size on mobile */
@media (max-width: 768px) {
  #adalong-widget {
    width: 100%;
  }
}

The widget will automatically adjust its layout to fit the available space while maintaining proper aspect ratios for thumbnails.

Classes

Some tags have classes starting with "adl-wdgt-" to help styling and customizing. You can also override this prefix by passing a string in the config object when instantiating the widget.

new AdalongWidget('token', {
  classPrefix: 'myPrefix',
});

CSS Selectors for customization

The widget provides several CSS class selectors that you can use to customize its appearance. Each class name is prefixed with the classPrefix value (default: adl-wdgt-). Here are the key selectors and how to use them:

Thumbnail Components

  • .{prefix}-thumbnail-content-active: Applied to the currently selected/active thumbnail (default z-index: 1000)
  • .{prefix}-thumbnail-content-inactive: Applied to non-active thumbnails (default z-index: 1)
  • .{prefix}-thumbnail-video: Applied to video elements within thumbnails when the video is being played (default z-index: 1001)
  • .{prefix}-thumbnail-pill: Applied to pill-shaped elements like username displays and mute buttons (default z-index: 1002)

Overlay

  • .{prefix}-overlay: The overlay background that appears when a post is opened (default z-index: 999)

Productlist Components

  • .{prefix}-productlist: The container for product listings in "Shop This Look" mode (default z-index: 1003)
  • .{prefix}-productlist-action-buttons: Action buttons in the product list view (default z-index: 1004)

Customizing z-index

If you experience z-index issues with thumbnails overlapping other page elements, you can override the z-index values. For example:

/* Reduce z-index of active thumbnails from 1000 to a lower value */
.adl-wdgt-thumbnail-content-active {
  z-index: 50 !important;
}

/* Also adjust related elements as needed */
.adl-wdgt-overlay {
  z-index: 49 !important;
}

Control Carousel with custom functions

The AdalongWidget class has some public functions that can be called to control the widget with custom code launched from outisde.

  public getSlideState(): { canSlideLeft: boolean, canSlideRight: boolean } {
    return {
        canSlideLeft: this.storeState.getState().canSlideLeft,
        canSlideRight: this.storeState.getState().canSlideRight,
    }
}

This function will tell you if the carousel is able to slide right or left, thus if there are more images to view in either direction. Then, you can call

 public setSlider(dir: 'left' | 'right') {
    dispatchEvent(new CustomEvent('adalongWidget_slide', {detail: dir}))
}

To trigger a movement in the carousel in the desired direction (by default new images are overflowing on the right).

The last function is to cycle through the elements in the carousel once their thumbnail has been clicked, and the popup with the details is shown:

public changePost(dir: 'left' | 'right') {
dispatchEvent(new CustomEvent('adalongWidget_changePost', { detail: dir }))
}

the 'left' input will open the previous media, while the 'right' input will open the next.

Shop this look

Add a "shop this look" section

The click on a "shop this look" link will by default open the product url. This behavior can be overridden by providing a function to the shopThisLookHandler field in the config object.

new AdalongWidget('token', {
  shopThisLookHandler: ({ media, product }, targetUrl) => {
    const url = new URL(targetUrl);
    url.searchParams.set('utm_source', 'source');
    url.searchParams.set('utm_medium', 'medium');
    window.open(url.href, '_blank');
  },
});

Customization

You can now fully customize the "shop this look" section according to your needs. This includes :

  • Partial customization :

    • "shop this look" text :
      • shopThisLookText?: string;
    • "more like this" text :
      • moreLikeThisText?: string;
    • arrows and background color, including the possibility to hide arrows in carousel mode, desktop and/or mobile :
      • hideArrows?: boolean;
      • displayMobileCarouselArrows?: boolean;
    • "shop this look" custom product buttons (for ex. to add a "Add to cart" or "Add to favorites" button) : See Shop this look custom product buttons

    • all options directly available through the widget editing tool in our app

partial customization visualization

  • Global customization :

    • Shop this look : When enabled, the "shop this look" section can be entirely replaced by a piece of code of your own creation.

full customization visualization

Shop this look custom product buttons

You can add up to four custom buttons to your products.

This function is called for each product when we have to render and must return an object with react components for rendering the custom buttons. All button events must be handled here following react rules.

Place this function in an object as a parameter of the function AdalongWidget.

 /**
   * @param react The react lib used by AdalongWidget
   * @param product Current rendered product
   * @param media Current opened media
   */
  getCustomProductButtons: (react, product, media) => {
    const addToCart = () =>
      react.createElement(
        'button',
        {
          onClick: () => handleAddToCart(),
        },
        '🛒'
      );
    const addToFavorites = () =>
      react.createElement(
        'button',
        {
          // ... same here
        },
        '♡'
      );
    return {
      topRight: addToCart,
      // each position is optional
      bottomRight: addToFavorites,
    };
  },

You can use four keys to position your custom buttons on the product image : topRight, bottomRight, topLeft, bottomLeft.

If you want to place two buttons next to each other on the product image, you can use react fragments to create a single element :

const twoButtons = () =>
  react.createElement(
    react.Fragment,
    null,
    react.createElement(
      'button',
      {
        onClick: () => handleAddToCart(),
      },
      '🛒',
    ),
    react.createElement(
      'button',
      {
        onClick: () => handleAddToFavorites(),
      },
      '❤️',
    ),
  );

Shop This Look entire customization

If you do not want to use the standard "Shop This Look" design, you can entirely customize this section to your needs, thanks to a rendering function called displayCustomShopThisLook.

In this function, you'll insert your piece of react or your react component as well as your logic in order to display it in place of the standard "Shop This Look". This function gives you the possibility to get all products-related info in order to map on it.

Here is a very simple example of the use of this function, by mapping on the products :

 /**
   * @param react The react lib used by AdalongWidget
   * @param products An array containing all related products
   * @param media Current opened media
   * @param isMobile If the widget is viewed in desktop mode (false) or mobile mode (true)
   */
    displayCustomShopThisLook: ({ react, products, media, isMobile, context }) => {
      const { createElement } = react;

      // Optional : Add the "Shop This Look" event tracking function
      const handleProductClick = (product, e) => {
        if (media) {
          context.triggerEvent('shopThisLook', {
            post: media,
            originalEvent: e,
            product: product.id,
          });
        }
      };

      // Map over the products array and create JSX elements for each product
      const productElements = products.map((product) =>
        createElement(
          'div',
          { key: product.id },
          createElement('img', { src: product.image_link, alt: product.title }),
          createElement('h3', null, product.title),
          createElement('p', null, product.description),
          createElement('p', null, `${product.price} ${product.currency}`),
          createElement('a', { href: product.link, onClick: (e) => handleProductClick(product, e), }, 'See the product'),
          createElement('button', null, createElement('i', { className: 'fa fa-heart' }))
        )
      );
      // Return the JSX to be rendered in place of the standard "Shop This Look" section
      return createElement(
        'div',
        null,
        createElement('h2', null, 'Custom Shop This Look'),
        ...productElements
      );
    },

Here is the info you'll receive about a product :

export interface IProduct {
  catalog_id: string;
  company_id: string;
  description: string;
  id: string;
  image_link: string;
  link: string;
  price?: number;
  currency?: string;
  title: string;
  updated_at: string;
  variant_name?: string;
}

Facebook Pixel Integration

You can leverage AdAlong widget events in your Facebook Pixel.

Add Facebook Pixel base code

First you have to follow those instructions to create a FB pixel. Once created, you need to add the following base code into the <head> tag of the page. Please note that you should reference your pixel id in two places.

<!-- Facebook Pixel Code -->
<script>
  !(function (f, b, e, v, n, t, s) {
    if (f.fbq) return;
    n = f.fbq = function () {
      n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);
    };
    if (!f._fbq) f._fbq = n;
    n.push = n;
    n.loaded = !0;
    n.version = '2.0';
    n.queue = [];
    t = b.createElement(e);
    t.async = !0;
    t.src = v;
    s = b.getElementsByTagName(e)[0];
    s.parentNode.insertBefore(t, s);
  })(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
  fbq('init', '{your-pixel-id-goes-here}');
  fbq('track', 'PageView');
</script>
<noscript>
  <img
    height="1"
    width="1"
    style="display:none"
    src="https://www.facebook.com/tr?id={your-pixel-id-goes-here}&ev=PageView&noscript=1"
  />
</noscript>
<!-- End Facebook Pixel Code -->

Track Events in your Facebook Pixel

Track standard Facebook events

Now to send information to Facebook from the AdAlong Widget you can map AdAlong events to Facebook standard events:

adalongWidget.onEvent('widgetLoaded', (event) => {
  fbq('track', 'ViewContent', { posts: event.posts });
});

Here is the full documentation on standard Facebook events

Track custom events

Now if you want to track specifically which post has been opened, and not only viewed, Facebook Pixel allows to track custom events following this model:

adalongWidget.onEvent('postOpened', (event) => {
  fbq('trackCustom', 'PostOpened', {
    post: event.post,
    productIds: event.post.products.map(({ id }) => id),
  });
});

Note that in the example we send information about which products the opened post illustrates.

Debugging

Use npm start to build and watch for changes.

Then use npm link to link this repo to another project in which to require the library.

You can also use node debug.js to directly test the library and display it on http://localhost:9800/?apiKey=yourWidgetKey