image

Beauty iFrame (version 1.9.41)


What is Beauty iFrame?

Beauty iFrame is an in-browser real-time augmented reality make-up web-app. The web-app allows for a fast, realistic live try-on experience on mobile or desktop directly from a brand’s web page.

Demo Try Me!


Browser Support

Holition Beauty’s virtual makeup engine (FaceSDK) depends on many modern Web-APIs which are not implemented by all browsers. The AR experience also depends on access to the device camera to operate.

Minimum Specification

The following are the minimum specifications required to operate:

Mobile
Desktop

Camera Access

The user must grant the web-app access to their camera to allow the experience to operate. A pop-up provided by the browser will be presented to the user upon initialisation.


Installing

The user can sign in to our Beauty Portal and use it for iFrame setup or choose manul way.

- Using Portal

Follow our Video Tutorial for installation

- Manual

To install the experience onto an existing web-page simply cut and paste the following HTML snippet into your page:

<iframe frameBorder="0" style="width: 100%;height: 100%;" allow="camera" src="https://<DEPLOYMENT-URL>?cms-client-id=<CMS-CLIENT-ID>&license=<LICENSE>"</iframe>

The HTML code inserts a configurable iFrame element into the page. In effect placing a virtual makeup experience into a resizable window onto your site.


Getting Started

There are two parts to setting up your virtual make-up experience. First the look and feel of the experience. Second the make up products and looks available to the users within.

Step 1. Configuring the Experience

The iFrame element allows for direct control over certain features and launch configurations of the web-app. These configurations are performed via URL parameters provided to the iFrame src attribute as follows:

<iframe frameBorder="0" style="width: 100%;height: 100%;" allow="camera" src="https://<DEPLOYMENT-URL>?cms-client-id=<CMS-CLIENT-ID>&configuration-id=<CONFIG-ID>&license=<LICENSE>&locale=<LOCALE>&identifier-type=<TYPE>&identifier-value=<VALUE>&range-id=<RANGE-ID>&looks=<BOOLEAN>&features=<OPTION>&carousel=<BOOLEAN>&filter=<BOOLEAN>&product-info=<BOOLEAN>&look-info=<BOOLEAN>&add-basket=<BOOLEAN>&watermark=<BOOLEAN>&vtoggle=<BOOLEAN>&info-button=<BOOLEAN>&ga-tracking=<BOOLEAN>&static-start=<BOOLEAN>&simplify-carousel-info=<BOOLEAN>&range-name=<RANGE-NAME>&beautify=<FILTER-NAME>"</iframe>

[NB. URL parameters take priority over CMS settings]

To control the look and feel of the virtual experience either:

  1. Add additional parameters to the iFrame element src URL to enable features or launch with specific looks or products set
Parameters
"aa" | "ab" | "ae" | "af" | "af-za" | "ak" | "am" | "am-et" | "an" | "ar" | "ar-ae" | "ar-bh" | "ar-dz" | "ar-eg" | "ar-iq" | "ar-jo" | "ar-kw" | "ar-lb" | "ar-ly" | "ar-ma" | "ar-om" | "ar-qa" | "ar-sa" | "ar-sy" | "ar-tn" | "ar-ye" | "as" | "av" | "ay" | "az" | "az-cyrl-az" | "az-latn-az" | "ba" | "be" | "be-by" | "bg" | "bg-bg" | "bh" | "bi" | "bm" | "bn" | "bn-in" | "bo" | "br" | "br-fr" | "bs" | "bs-cyrl-ba" | "bs-latn-ba" | "ca" | "ca-es" | "ce" | "ch" | "co" | "cr" | "cs" | "cs-cz" | "cu" | "cv" | "cy" | "da" | "da-dk" | "de" | "de-at" | "de-ch" | "de-de" | "div-mv" | "dv" | "dz" | "ee" | "el" | "el-gr" | "en" | "en-au" | "en-bz" | "en-ca" | "en-gb" | "en-ie" | "en-jm" | "en-nz" | "en-ph" | "en-tt" | "en-us" | "en-za" | "en-zw" | "eo" | "es" | "es-ar" | "es-bo" | "es-cl" | "es-co" | "es-cr" | "es-do" | "es-ec" | "es-es" | "es-gt" | "es-hn" | "es-mx" | "es-ni" | "es-pa" | "es-pe" | "es-pr" | "es-py" | "es-sv" | "es-uy" | "es-ve" | "et" | "et-ee" | "eu" | "eu-es" | "fa" | "fa-ir" | "ff" | "fi" | "fi-fi" | "fj" | "fo" | "fo-fo" | "fr" | "fr-be" | "fr-ca" | "fr-ch" | "fr-fr" | "fr-lu" | "fr-mc" | "fy" | "ga" | "gd" | "gl" | "gl-es" | "gn" | "gu" | "gu-in" | "gv" | "ha" | "he" | "he-il" | "hi" | "hi-in" | "ho" | "hr" | "hr-hr" | "ht" | "hu" | "hu-hu" | "hy" | "hy-am" | "hz" | "ia" | "id" | "id-id" | "ie" | "ig" | "ii" | "ik" | "io" | "is" | "is-is" | "it" | "it-ch" | "it-it" | "iu" | "ja" | "ja-jp" | "jv" | "ka" | "ka-ge" | "kg" | "ki" | "kj" | "kk" | "kk-kz" | "kl" | "km" | "km-kh" | "kn" | "kn-in" | "ko" | "ko-kr" | "kok-in" | "kr" | "ks" | "ku" | "kv" | "kw" | "ky" | "ky-kz" | "la" | "lb" | "lg" | "li" | "ln" | "lo" | "lo-la" | "lt" | "lt-lt" | "lu" | "lv" | "lv-lv" | "mg" | "mh" | "mi" | "mi-nz" | "mk" | "mk-mk" | "ml" | "mn" | "mn-mn" | "mr" | "mr-in" | "ms" | "ms-bn" | "ms-my" | "mt" | "my" | "na" | "nb" | "nb-no" | "nd" | "ne" | "ng" | "nl" | "nl-be" | "nl-nl" | "nn" | "nn-no" | "no" | "nr" | "nv" | "ny" | "ny-mw" | "oc" | "oj" | "om" | "or" | "os" | "pa" | "pa-in" | "pi" | "pl" | "pl-pl" | "ps" | "pt" | "pt-br" | "pt-pt" | "qu" | "rm" | "rn" | "ro" | "ro-ro" | "ru" | "ru-ru" | "rw" | "sa" | "sa-in" | "sc" | "sd" | "se" | "sg" | "si" | "sk" | "sk-sk" | "sl" | "sl-sl" | "sm" | "sn" | "so" | "sq" | "sq-al" | "sr" | "sr-cyrl-rs" | "sr-latn-rs" | "ss" | "st" | "su" | "sv" | "sv-fi" | "sv-se" | "sw" | "sw-tz" | "syr-sy" | "ta" | "ta-in" | "te" | "te-in" | "tg" | "th" | "th-th" | "ti" | "tk" | "tl" | "tn" | "to" | "tr" | "tr-tr" | "ts" | "tt" | "tt-ru" | "tw" | "ty" | "ug" | "uk" | "uk-ua" | "ur" | "ur-pk" | "uz" | "uz-cyrl-uz" | "uz-latn-uz" | "ve" | "vi" | "vi-vn" | "vo" | "wa" | "wo" | "xh" | "yi" | "yo" | "za" | "zh" | "zh-chs" | "zh-cht" | "zh-cn" | "zh-hk" | "zh-mo" | "zh-sg" | "zh-tw" | "zu" | "zu-za"

  1. Use the Holition Beauty CMS to configure button icons, copy and enabled features
    To use the CMS configuration the configuration-id iFrame parameter, described above, must be supplied with a valid config ID (found from the CMS administration control panel)

_[NB. URL parameters take priority over CMS settings.

Step 2. Configuring make up products and looks

The second step is to set-up the virtual products in our CMS. This includes setting product images (thumbnails and packshots), names, descriptions and also the colour calibrations of the products themselves. To access the CMS please goto the portal cms. For assistance with calibration please see our Portal Guide]_


API

The web-app allows for both dynamic control (actions) and real-time event reporting (events) to and from the parent host page.

Events

To listen to all internal events from the iframe just add the following script to your page, which will subscribe to events from the iFrame:

// Add window event listener functions
if (window.addEventListener) {
  window.addEventListener('load', handleForm, false);
  window.addEventListener('message', handleMessage, false);
}

// Subscribe to events when iFrame has loaded
function handleForm() {
  // Subscribe to events
  var win = document.getElementById('facesdk').contentWindow;
  win.postMessage(
    'subscribe',
    'https://holition-beauty-projects.holitionbeauty.com'
  );
}

// Handle events messages
function handleMessage(e) {
  if (e.origin !== 'https://holition-beauty-projects.holitionbeauty.com') {
    return;
  }

  const event = e.data;
  // [Respond to event messages here]
  console.log(
    `FaceSDK Event: component[${event.component}] type[${event.type}] data:`,
    event.data
  );
}

Upon subscription an event will be returned with the current SDK version number as follows:

interface Event {
  version: string;
}

Event responses are JSON formated as follows:

interface Event {
  component:
    | 'face_scan'
    | 'slider'
    | 'photo'
    | 'products'
    | 'sdk'
    | 'static_image';
  type:
    | 'scan_progress'
    | 'scan_results'
    | 'scan_button_click'
    | 'slider_button_click'
    | 'slider_thumb_drag'
    | 'close_photo_button_click'
    | 'save_photo_button_click'
    | 'photo_button_click'
    | 'photo_captured'
    | 'select_product'
    | 'select_look'
    | 'select_range'
    | 'select_filter'
    | 'initialised'
    | 'face_tracked'
    | 'camera_access'
    | 'feed_error'
    | 'error'
    | 'critical_error'
    | 'add_basket'
    | 'info_view'
    | 'info_close'
    | 'info_button'
    | 'image_select'
    | 'live_launch'
    | 'image_align_click'
    | 'finish_image_align'
    | 'static_launch'
    | 'filtered_products'
    | 'data_loaded';
  data: any | null;
}

Face-Scan

All face-scan related events have event_component set to face_scan.

Getting Results

The result of the face scan

interface Event {
  component: 'face_scan';
  type: 'scan_results';
  data: {
    results: {
      eyeColor: 'black' | 'blue' | 'brown' | 'green' | 'grey';
      eyeColorProbabilities: {
        black: number;
        blue: number;
        brown: number;
        green: number;
        grey: number;
      };
      eyeColorProbability: number;
      eyeShape: 'almond' | 'downturned' | 'rounded' | 'upturned';
      eyeShapeProbabilities: {
        almond: number;
        downturned: number;
        rounded: number;
        upturned: number;
      };
      eyebrowShape: 'high_arch' | 'straight' | 'thick';
      eyebrowShapeProbabilities: {
        high_arch: number;
        straight: number;
        thick: number;
      };
      faceShape: 'heart' | 'oval' | 'rounded' | 'square';
      faceShapeProbabilities: {
        heart: number;
        oval: number;
        rounded: number;
        square: number;
      };
      lipCoverage: 'full' | 'medium' | 'thin';
      lipCoverageProbabilities: {
        full: number;
        medium: number;
        thin: number;
      };
      mediaInputQuality: string;
      percentage: number;
      skinTone: 'dark' | 'deep' | 'light' | 'light_medium' | 'medium';
      skinToneProbabilities: {
        dark: number;
        deep: number;
        light_medium: number;
        light: number;
        medium: number;
      };
      skinToneProbability: number;
    };
  };
}
Seeing Progress

The progress of the face-scan

interface Event {
  component: 'face_scan';
  type: 'scan_progress';
  data: {
    progress: number;
  };
}
Notified When Starting

User has started the face scan experience

interface Event {
  component: 'face_scan';
  type: 'scan_button_click';
  data: null;
}

Slider interaction

All slider related events have event_component set to slider.

Slider Start

User activating slider

interface Event {
  component: 'slider';
  type: 'slider_button_click';
  data: {
    enabled: boolean;
    product: {
      // Unique CMS ID
      id: string;
      status: 'active' | 'inactive';
      schema: {};
      set: {};
      group: {};
      meta: {};
      region: {};
      data: {};
      rendering: {};
    };
    look: {
      self: {
        // Unique CMS ID for look
        id: string;
        schema: {};
        set: {};
        group: {};
        meta: {};
        region: {};
        status: 'active' | 'inactive';
        data: {};
        rendering: {};
      };
      // List of products included in look
      products: [];
    };
  };
}
Slider Drag

User sliding the slider

interface Event {
  component: 'slider';
  type: 'slider_thumb_drag';
  data: {
    // slider position (ranging from 0 - 1 | left - right)
    position: number;
  };
}

Take-A-Photo

All photo related events have event_component set to photo.

Take-A-Photo Start

User activating take-a-photo

interface Event {
  component: 'photo';
  type: 'photo_button_click';
  data: {
    product: {
      // Unique CMS ID
      id: string;
      status: 'active' | 'inactive';
      schema: {};
      set: {};
      group: {};
      meta: {};
      region: {};
      data: {};
      rendering: {};
    };
    look: {
      self: {
        // Unique CMS ID for look
        id: string;
        schema: {};
        set: {};
        group: {};
        meta: {};
        region: {};
        status: 'active' | 'inactive';
        data: {};
        rendering: {};
      };
      // List of products included in look
      products: [];
    };
  };
}
Close Photo Display

User closed photo display overlay

interface Event {
  component: 'photo';
  type: 'close_photo_button_click';
  data: null;
}
Save Photo Display

User saved photo to device

interface Event {
  component: 'photo';
  type: 'save_photo_button_click';
  data: null;
}
Photo Captured

Photo captured

interface Event {
  component: 'photo';
  type: 'photo_captured';
  data: base64;
}

Product Events

All product, range or look selection events have event_component set to products.

Product Selected

User selected a product

interface Event {
  component: 'products';
  type: 'select_product';
  data: {
    product: {
      // Unique CMS ID
      id: string;
      status: 'active' | 'inactive';
      schema: {};
      set: {};
      group: {};
      meta: {};
      region: {};
      data: {};
      rendering: {};
    };
  };
}
Dwell Product

User dwell time on selected product

interface Event {
  component: 'products';
  type: 'dwell_product';
  data: {
    product: {
      // Unique CMS ID
      id: string;
      status: 'active' | 'inactive';
      schema: {};
      set: {};
      group: {};
      meta: {};
      region: {};
      data: {};
      rendering: {};
    };
    dwell: number;
  };
}
Range Selected

User selected a range

interface Event {
  component: 'products';
  type: 'select_range';
  data: {
    product: {
      // Unique CMS ID
      id: string;
      status: 'active' | 'inactive';
      schema: {};
      set: {};
      group: {};
      meta: {};
      region: {};
      data: {};
      rendering: {};
    };
  };
}
Filtered Product List

Filtered product list based on face-scan results

interface Event {
  component: 'products';
  type: 'filtered_products';
  data: {
    products: [];
  };
}
Product Information View Selected

User activated product info view

interface Event {
  component: 'products';
  type: 'info_view';
  data: {
    product: {
      // Unique CMS ID
      id: string;
      status: 'active' | 'inactive';
      schema: {};
      set: {};
      group: {};
      meta: {};
      region: {};
      data: {};
      rendering: {};
    };
  };
}
Product Information View Closed

User closed product info view

interface Event {
  component: 'products';
  type: 'info_close';
  data: {
    product: {
      // Unique CMS ID
      id: string;
      status: 'active' | 'inactive';
      schema: {};
      set: {};
      group: {};
      meta: {};
      region: {};
      data: {};
      rendering: {};
    };
  };
}
Product Added to Basket

User chose to add current product to basket

interface Event {
  component: 'products';
  type: 'add_basket';
  data: {
    product: {
      // Unique CMS ID
      id: string;
      status: 'active' | 'inactive';
      schema: {};
      set: {};
      group: {};
      meta: {};
      region: {};
      data: {};
      rendering: {};
    };
  };
}
Filter Selected

User selected a product filter

interface Event {
  component: 'products';
  type: 'select_filter';
  data: {
    filter:
      | 'blusher'
      | 'bronzer'
      | 'lipstick'
      | 'lipliner'
      | 'eyeshadow'
      | 'eyeliner'
      | 'foundation'
      | 'concealer'
      | 'eyebrow'
      | 'masacara';
  };
}
VToggle Selected

User selected to toggle between product and looks

interface Event {
  component: 'products';
  type: 'select_vtoggle';
  data: {
    vtoggle:
      | 'products'
      | 'looks';
  };
}

Look Events

All product, range or look selection events have event_component set to products.

Look Information View Selected

User activated look info view

interface Event {
  component: 'products';
  type: 'info_view';
  data: {
    look: {
      self: {
        // Unique CMS ID for look
        id: string;
        schema: {};
        set: {};
        group: {};
        meta: {};
        region: {};
        status: 'active' | 'inactive';
        data: {};
        rendering: {};
      };
      // List of products included in look
      products: [];
    };
  };
}
Look Information View Closed

User closed look info view

interface Event {
  component: 'products';
  type: 'info_close';
  data: {
    look: {
      self: {
        // Unique CMS ID for look
        id: string;
        schema: {};
        set: {};
        group: {};
        meta: {};
        region: {};
        status: 'active' | 'inactive';
        data: {};
        rendering: {};
      };
      // List of products included in look
      products: [];
    };
  };
}
Look Added to Basket

User chose to add current look to basket

interface Event {
  component: 'products';
  type: 'add_basket';
  data: {
    look: {
      self: {
        // Unique CMS ID for look
        id: string;
        schema: {};
        set: {};
        group: {};
        meta: {};
        region: {};
        status: 'active' | 'inactive';
        data: {};
        rendering: {};
      };
      // List of products included in look
      products: [];
    };
}
Look Selected

User selected a look

interface Event {
  component: 'products';
  type: 'select_look';
  data: {
    look: {
      self: {
        // Unique CMS ID for look
        id: string;
        schema: {};
        set: {};
        group: {};
        meta: {};
        region: {};
        status: 'active' | 'inactive';
        data: {};
        rendering: {};
      };
      // List of products included in look
      products: [];
    };
  };
}
Dwell Look

User dwell time for selected look

interface Event {
  component: 'products';
  type: 'dwell_look';
  data: {
    look: {
      self: {
        // Unique CMS ID for look
        id: string;
        schema: {};
        set: {};
        group: {};
        meta: {};
        region: {};
        status: 'active' | 'inactive';
        data: {};
        rendering: {};
      };
      // List of products included in look
      products: [];
    };
    dwell: number;
  };
}

SDK Status

All SDK related events have event_component set to sdk.

SDK Initialised

SDK has initialised

interface Event {
  component: 'sdk';
  type: 'initialised';
  data: {
    status: boolean;
  };
}
Face Tracked

User face detected and tracked

interface Event {
  component: 'sdk';
  type: 'face_tracked';
  data: {
    status: boolean;
  };
}
Camera Access

Has user camera access been aquired

interface Event {
  component: 'sdk';
  type: 'camera_access';
  data: {
    status: boolean;
  };
}
Camera Feed Error

Camera has failed to start correctly

interface Event {
  component: 'sdk';
  type: 'feed_error';
  data: null;
}
Internal SDK Error

All internal FaceSDK errors - see SDK docuementation for more information

interface Event {
  component: 'sdk';
  type: 'error';
  data: {
    error: any;
  };
}
Critical Error

FaceSDK has experienced a critical error relating to hardware/browser incompatability.

interface Event {
  component: 'sdk';
  type: 'critical_error';
  data: {
    error: any;
  };
}
Info Button Clicked

General information button clicked

interface Event {
  component: 'sdk';
  type: 'info_button';
  data: null;
}

Static Image Upload

All image upload related events have event_component set to image_upload.

Select Image

User asked to select an image to upload

interface Event {
  component: 'image_upload';
  type: 'image_select';
  data: null;
}
Live Launch

SDK was launched with live camera view

interface Event {
  component: 'image_upload';
  type: 'live_launch';
  data: null;
}
Align Image

User clicked to button to align uploaded image (scale | flip | rotate)

interface Event {
  component: 'image_upload';
  type: 'image_align_click';
  data: {
    scale: number;
    flipV: boolean;
    flipH: boolean;
    rotate: number;
  };
}
Finish Alignment

User has finished aligning the image

interface Event {
  component: 'image_upload';
  type: 'finish_image_align';
  data: null;
}
Static Launch

SDK was launched with a static image

interface Event {
  component: 'image_upload';
  type: 'static_launch';
  data: null;
}

Actions

The iframe can be remotely controlled by sending actions in to it.

interface Action {
  command: string;
  data: any | null;
}

Set Product

Send the below action to set the active product

interface Action {
  command: 'set_product';
  data: {
    id: string;
    idType:
      | 'cms-id'
      | 'SKU'
      | 'EAN'
      | 'UPC'
      | 'GTIN'
      | 'ASIN'
      | 'Shade'
      | 'Range'
      | 'Other';
  };
}

Example:

// Set active product
function setProduct(productId, idType) {
  var win = document.getElementById('facesdk').contentWindow;
  const sendToFaceSdk = (action) =>
    win.postMessage(
      JSON.stringify(action),
      'https://holition-beauty-projects.holitionbeauty.com'
    );

  sendToFaceSdk({
    command: 'set_product',
    data: {
      id: productId,
      idType: idType,
    },
  });
}

Set Look

Send the below action to set the active look

interface Action {
  command: 'set_look';
  data: {
    id: string;
  };
}

Example:

// Set active look
function setLook(lookId) {
  var win = document.getElementById('facesdk').contentWindow;
  const sendToFaceSdk = (action) =>
    win.postMessage(
      JSON.stringify(action),
      'https://holition-beauty-projects.holitionbeauty.com'
    );

  sendToFaceSdk({
    command: 'set_look',
    data: {
      id: lookId,
    },
  });
}

Build Look

Send the below action to build a look from a set of products

type IdentifierType =
  | 'cms-id'
  | 'sku'
  | 'ean'
  | 'upc'
  | 'gtin'
  | 'asin'
  | 'shade'
  | 'range'
  | 'other';

interface ItemIdentifier {
  readonly type: IdentifierType;
  readonly value: string;
}

interface Action {
  command: 'build_look';
  data: {
    ids: ItemIdentifier[];
  };
}

Example:

// Set dynamic look
function buildLook(items : ItemIdentifier[]) {
  var win = document.getElementById('facesdk').contentWindow;
  const sendToFaceSdk = (action) =>
    win.postMessage(
      JSON.stringify(action),
      'https://holition-beauty-projects.holitionbeauty.com'
    );

  sendToFaceSdk({
    command: 'build_look',
    data: {
      ids: items,
    },
  });
}

Take Picture

Request picture be taken

interface Action {
  command: 'take_picture';
  data: {};
}

Example:

// Take picture
function takePicture(productId, idType) {
  var win = document.getElementById('facesdk').contentWindow;
  const sendToFaceSdk = (action) =>
    win.postMessage(
      JSON.stringify(action),
      'https://holition-beauty-projects.holitionbeauty.com'
    );

  sendToFaceSdk({
    command: 'take_picture',
    data: {},
  });
}

Data Loaded

FaceSDK has loaded product data correctly

interface Event {
  component: 'sdk';
  data: null;
  type: 'data_loaded';
}