1.1 Fit Finder Widget

The Fit Finder integration produces two scripts:

  • The pdp.js script, which will be added to (all) Product Detail Pages (PDP). This script serves to:

    • Install the Fit Finder button, through which the user can open the Fit Finder size advisor, on the PDP.
    • Collect and send all the necessary data from the shop to the Fit Finder database to provide a recommendation.
  • The orderconfirmation.js script, which will be added to the checkout / Order Confirmation Page (OCP). This script serves at the end of the user journey to:

    • Connect items with a size recommendation and the purchased item.
    • Help improve fit prediction models and the size recommendation engine.
    • Collect purchase data for Fit Insights reports.

Neither of the scripts collects or stores any personal identifiable information on a user.

1.2 Integration Data Objects

Fit Finder relies on various elements of a shop’s website, which means the integration can be impacted by any changes made to these dependencies. Changes to a shop’s infrastructure or design can be expected over time but might cause Fit Finder to no longer load correctly.

Therefore Fit Finder integrations are built in a way to prevent these outages, resulting from changes to the dependency elements. To do our best to ensure a stable integration we recommend providing data objects on the PDP (Product Detail Page) and OCP (Order Confirmation Page). Your technical resources will be responsible for implementing these objects.

Considerations to take into account:

  • The PDP object should update whenever the user changes the color or navigates to a different product.
  • The objects should be placed directly on the page and not via tag manager (e.g. Google Tag Manager).
  • The size values in the objects should match the values in the product and return feeds.
  • All functions should be implemented by you in your preferred method as long as they provide the expected values and behaviour. Some functions are only needed in case of additional functionalities and features so please refer to the "Description" column in the table below for the specific use cases.
  • experimentFunnel is reported in case of an external A/B test. You’re free to select the value as you see fit (it should identify a given funnel used on the page).
  • For an explanation of shop session ID please look at a section of the page dedicated to that.
  • All properties are required unless marked with a question mark following the property name. There are some special cases, which are flagged in the property description in the table below.


Product Detail Page (PDP) Object

+
type fitAnalyticsData = {
    shopLanguage: string
    shopCountry: string
    mainImageLink: string
    user: {
      id: string | null
      hasLoggedIn: boolean
    }
    currentItemSubgroupId: string
    allItemSubgroupIds: string[]
    shopSessionId: string
    experimentFunnel?: string
    sizes: {
        value: string
        isAvailable: boolean
    }[]
    consent: {
        hasAnalyticsConsent?(): Promise | boolean {},
    },
    operations: {
        getAddToCartBtn(): HTMLElement {},
        getSizeChartLink(): HTMLElement {},
        addToCart(itemSubgroupId: string, size: string): void {},
        selectSize(itemSubgroupId: string, size: string): void {},
        getCurrentSize(): string {},
        getCartItems(): Promise>|Array<{itemSubgroupId: string, size: string}> {}
    }
}
Property Description
shopLanguage ISO 639-1, e.g. ‘en’
shopCountry ISO 3166-1, e.g. ‘GB’
mainImageLink URL to a product picture that will be displayed within the widget. Reminder: the value should be updated in case a visitor selects a different color.
user.id In case that a user is logged in, it should be a unique user identifier. It shouldn’t depend on the session and it should be consistent and have the same value in both data objects. In case of visitors that aren’t logged in it should be null.
currentItemSubGroupId The current item subgroup ID is a color-level identifier for the product the user is currently looking at.
allItemSubgroupIds Contains all item subgroup IDs for different colors of the product (and because of that it should contain the currentItemSubgroupId value).
sizes Is an array of objects, which correspond to the different sizes on the PDP. Each size object should have two properties: the size value and the value of the availability. The size value should be identical to the one in the feed. In case of 2D sizes (e.g. width and length) we need all combinations e.g. “40 long” (that again match the format as the sizes in the feed).
consent.hasAnalyticsConsent This function should return the explicit consent state given by the user after interacting with your cookie consent banner. You should return true if the visitor has either clicked on "Accept All" or specifically clicked on the option that allows FitFinder to track session identifiers. You should return false if the visitor has either closed the consent banner, clicked on "Reject All" or specifically clicked on the option that rejects FitFinder to track session identifiers.
operations.getAddToCartBtn This function should return the HTML element of the add to cart button.
operations.getSizeChartLink This function should return the HTML element of the size chart button.
operations.addToCart This function should add a given size of a given product to cart.
operations.selectSize This function should select a given size for a given product on the page.
operations.getCurrentSize This function should return the currently selected size. Required in case we should provide our multiple size alert (MSA) feature, otherwise optional.
operations.getCartItems This function should return the products currently in cart. Required in case we should provide our multiple size alert (MSA) feature, otherwise optional.

Example object
fitAnalyticsData = {
    shopLanguage: "de",
    shopCountry: "DE",
    mainImageLink: "https://example.com/de_de/example-product.jpg",
    user: {
      id: "qvfu93nh9q8ufv389qnh3quw3u"
      hasLoggedIn: true
     },
    currentItemSubgroupId: "19603829",
    allItemSubgroupIds: ["19603828", "19603827", "19603829", "19603821"],
    shopSessionId: "aa9a93gbhna93hna9hnsi9aahn",
    experimentFunnel: "control",
    sizes: [
        { value: "42", isAvailable: true },
        { value: "44", isAvailable: false },
        { value: "46", isAvailable: false }
    ],
    consent: {
        hasAnalyticsConsent() {...}
    },
    operations: {
        getAddToCartBtn: function () {...},
        getSizeChartLink: function () {...},
        addToCart: function (currentItemSubgroupId, size) {...},
        selectSize: function (currentItemSubgroupId, size) {...},
        getCurrentSize: function () {...},
        getCartItems: function () {...}
    },
}


Order Confirmation Page (OCP) Object

+
type fitAnalyticsData = {
  orderId: string
  shopLanguage: string
  shopCountry: string
  currency: string
  user: {
    id: string | null
    hasLoggedIn: boolean
  }
  shopSessionId: string
  experimentFunnel?: string
  products: {
    size: string,
    itemId: string
    itemSubgroupId: string
    price: number | string
    quantity: number | string
    gtin: string
  }[]
}
Property Description
orderId The order ID of the purchase, should match what’s displayed on the purchase success page.
shopLanguage ISO 639-1, e.g. ‘en’
shopCountry ISO 3166-1, e.g. ‘GB’
currency The currency that the visitor paid in, should be ISO 4217, e.g. 'EUR’.
user.id In case that a user is logged in, it should be a unique user identifier. It shouldn’t depend on the session and it should be consistent and have the same value in both data objects. In case of visitors that aren’t logged in it should be null.
product.size The size of the product that the user purchased, this value should always match the value on the PDP and in the feed.
product.itemId A size-level identifier of a product. This value should match the item_id (or equivalent) in the returns feed and the id (or equivalent) field in the product feed.
product.itemSubgroupId A color-level identifier. It needs to match the value from the PDP data object and the product feed column that contains these identifiers.
product.price The unit price that the user paid to purchase the product (including taxes and discounts).
product.quantity The quantity that the user purchased of a specific product.
product.gtin A unique product identifier, usually 13 digits long. https://en.wikipedia.org/wiki/Global_Trade_Item_Number

Example object
fitAnalyticsData = {
  orderId: "127591",
  shopLanguage: "de",
  shopCountry: "DE",
  currency: "USD",
  user: {
    id: "qvfu93nh9q8ufv389qnh3quw3u",
    hasLoggedIn: true
  }
  shopSessionId: "aa9a93gbhna93hna9hnsi9aahn",
  products: [
    {
      size: "42",
      itemId: "1960382803",
      itemSubgroupId: "19603828",
      price: 27.99,
      quantity: 2,
      gtin: "5714559416776"
    },
    {
      size: "46",
      itemId: "1960382705",
      itemSubgroupId: "19603827",
      price: 48.99,
      quantity: 1,
      gtin: "8255183046278"
    },
    //... the same per each purchased product
  ],
}


Shop Session ID

Due to updated security policies on iOS devices, it is often not possible for Fit Finder scripts to interact with 3rd party cookies, such as connect.sid. This is a growing issue, as our data shows that more users are viewing Fit Finder on iOS devices. Lack of session ID’s lead to issues tracking the user journey between PDP and OCP.

A solution for this problem is to retrieve a first party (generated shop side) session ID. In the integration object, it’s called shop session ID. The primary location for such an ID is a first party cookie, native to the shop’s site, though any identifier may be used as long as it adheres to these criteria:

  • It should be unique per visitor and preserved between visits from the same browser for the duration of their session.
  • Its value must stay the same when the visitor logs in or out.
  • It needs to be accessible on both PDP and OCP and it must have the same value for a single visitor on both pages
  • It should be safe from misuse in case. For example it shouldn't be possible to impersonate and/or personally identify the visitor in any way with just this identifier.
  • It could be theoretically derived from the shop's internal session ID, however then it should be definitely protected (e.g. hashed with a secure hash function like SHA256), to prevent abuse as described.
  • It must be readable by JavaScript. This means cookies with the httpOnly flag are not suited for this purpose.

1.3 Data Object Validator

The Fit Finder data object validator is a way to test and validate that the data objects, being implemented by the shop’s technical resources, is as expected, all mandatory properties are there, property values are in the correct type and format, and operations are working properly.

The solution we have now is a simple js script that when run on a PDP with data object, it reads the object, validates the data and logs the validation results on the browser’s console.

How to use the script:

  • Calling the links:

The script can be called externally on a PDP / OCP with the data object provided. https://osiris.fitanalytics.com/pdp-checker.osiris.js

  • Using a JS injector:

A simple JS injector can be used to inject the script into the PDP / OCP with the data object provided.

The data object validation results can then be seen by opening the devTools' console tab.

1.4 Immediate Recommendation

Once a user has completed the recommendation flow and received a size recommendation, Fit Finder delivers size recommendations on the following Product Detail Pages (PDPs). This feature allows Fit Finder users to obtain recommendations immediately during the shopping journey or upon a user’s return to any supported PDP on the shop. The Fit Finder call to action (CTA) button will change to the immediate recommendation text for returning users and they will not have to go through the flow again.



Fit Finder Click To Action Text

Fit Finder Immediate Recommendation Text

1.5 Order Confirmation Page

Fit Finder integration produces two scripts, one script that runs on the product detail page and enables the visual front end functionality of Fit Finder and one script that runs on the checkout/order confirmation page. The orderconfirmation.js script, serves at the end of the user journey to connect purchases, track the user journey from size recommendation to purchase and helps improve fit prediction models.

1.6 Customization

Parts of the Fit Finder experience can be customized to support a shop’s visual brand guidelines. Within Fit Finder standard integration these following elements are customizable:

Shop Logo:

dimensions of the logo placeholder are W: 200 px and H: 60px max or higher resolution.limit: Logo should not be bigger than 10 MB.Format: The best option is SVG, however we can also work with JPG and PNG. If a shop can’t provide one of the latter formats, the resolution of the image should be at least 300ppi.

Button Color:

(CTA) button, Immediate recommendation (IR) button, Add-to-Cart (A2C) button and feature tool tips, can be customized in a brand color.brand colors must be specified as a six-digit hexadecimal valueCTA button and tool tips, different brand color can be used, a primary HEX and secondary HEXmost cases the Primary HEX should be dark enough for the text upon it to be white as it is here:

Classic Fit Finder Designs:

Custom Color Design:

Customizable Tool Tips:

1.7 How does widget.js work

To interact with Fit Finder, the widget needs to collect certain information, such as the shop country, the language, the color-id of the selected product. The Fit Finder script fetches this information on the shop and will also install the button. The widget’s size is written in native coffeescript without relying on frameworks for various reasons:

  • the widget’s size is minimal
  • the widget is cross platform and works with different client shops
  • we have full control over widget functionalities

After collecting the necessary data and interacting with a user, Fit Finder recommends a size to the user, and user feed data is stored in the widget. In this process no personal identifiable data of any user is used or stored.

1.8 Compatibility

Fit Finder’s current code base offers support for a wide range of legacy browsers and devices. It can operate without jQuery or alternatively, load jQuery 1.8.3 in noConflict mode, unless there is already a jQuery library with version 1.7 or newer present. To avoid version conflicts with different jQuery libraries, please make sure to run any critical code that relies on older jQuery versions before loading the Fit Finder widget code.

Questions?

We're happy to help. Send your question to support@fitanalytics.com.