Web / JavaScript Library

Start Here

The Froomle Web SDK lets you inject personalized recommendations into your website, no matter how it is rendered. It automatically handles user attribution, interaction tracking (page visits, impressions, clicks), retrieves the right recommendation lists, and fills your HTML placeholders with the correct content. What you can do out of the box:

  • Render recommendations in static HTML using declarative data-froomle-* attributes.

  • Drive dynamic apps with a TypeScript-friendly API (setFroomleUserId, custom order methods, callbacks, …​).

  • Embed SDK calls server side (PHP today) to pre-render markup before it reaches the browser.

  • Combine these approaches—e.g. preload lists in JS, then let data attributes populate the DOM when components mount.

Installation

  • HTML

  • NPM

  • Packagist

When working with static HTML files, the simplest way to include the library is by adding the following <script> tag to your page:

<script src="<!-- Link will be provided soon -->"></script>

For npm-based workflows, install the library via:

npm install froomle-sdk
The npm package is not yet available.
composer require froomle/froomle-sdk
The package is not yet available on Packagist.

Library Parameters

Environment

Defines the Froomle environment to be used.

  • HTML

  • Javascript

  • PHP

Use data-froomle-env to set the environment.

<script data-froomle-env="my_env"></script>

setFroomleEnvironment(environment: string): void

Sets the environment.

setFroomleEnvironment("env_id");

setFroomleEnvironment(string $environment): void

setFroomleEnvironment("env_id");

Users

A user is any individual to whom you can offer items across any of your channels or devices. Froomle supports two mechanisms for identifying users in its APIs: device_id, user_id.

Froomle can work with either identifier, but the chosen ID should remain stable across recommendation requests for accurate personalization and analytics. More info on users can be found here.


Device ID

A device_id is an identifier associated with a specific device or browser. It should remain stable over time, as long as the user keeps using the same device.

Common examples:

  • persistent browser cookie ID

  • app installation ID

  • local device-level storage identifier

The device ID will be set automatically unless overridden.

  • HTML

  • Javascript

  • PHP

Use data-froomle-device-id to explicitly set the device ID.

<script data-froomle-device-id="device1"></script>

setFroomleDeviceId(device_id: string): void

Sets the user ID.

setFroomleDeviceId("device1");

setFroomleDeviceId(string $device_id): void

setFroomleDeviceId("device1");

User ID

A user_id is a more permanent, cross-device identifier. It remains the same regardless of the device used and allows you to recognize the same user across multiple sessions and platforms.

Common examples:

  • login ID

  • account ID

  • customer identifier stored in your backend

Use user_id whenever you can reliably identify authenticated users.

  • HTML

  • Javascript

  • PHP

Use data-froomle-user-id to set the user ID.

<script data-froomle-user-id="user3"></script>

setFroomleUserId(user_id: string): void

Sets the user ID.

setFroomleUserId("user1");

setFroomleUserId(string $user_id): void

setFroomleUserId("user1");

Froomle supports three levels of user consent. These levels determine how recommendations are generated and what type of tracking is allowed.


User-based recommendations + impression tracking

At this level, Froomle:

  • generates recommendations based on the user’s history and behavior

  • tracks impressions of recommended items

  • provides the highest level of personalization

This level requires explicit consent from the user.


No user-based personalization, but impressions are tracked

At this level, Froomle:

  • tracks which recommendations are shown (impressions)

  • does not use any user history or behavioral data

  • provides non-personalized recommendations

This is suitable for users who allow analytics but not personalization.


No personalization, no impression tracking

At this level, Froomle:

  • does not track impressions

  • does not use any user-based data

  • still returns recommendations, but only based on popularity or similar non-personalized signals

Even with consent level 0, a recommendation request is still required so Froomle can return the appropriate popular items.

Froomle’s default consent level is 0.

You can set the consent level explicitly using the setFroomleConsent(level); JavaScript method.

setFroomleConsent(2);

The consent level only needs to be set once per device. This setting must be applied through JavaScript, as consent must be explicitly requested from and granted by the user in the browser.


Page Tracking Events

Page tracking events indicate what type of page the user is currently viewing. They allow Froomle to understand whether the user is on:

  • a specific item page (e.g., article, product, video)

  • a homepage

  • a category or section page

  • any other generic page

By knowing the context of the page, Froomle can better tailor recommendations and improve relevance.


Detail Pageview

A detail pageview occurs when a user opens the page of a specific item. This event is linked to exactly one item.

Common examples include:

  • article detail pages

  • video detail pages

  • product detail pages

  • HTML

  • Javascript

  • PHP

Use data-froomle-pageview-<pagetype>="<item_id>"

example:

<script data-froomle-pageview-article_detail="item437"></script>

Use setFroomlePageView(<pagetype>: string, <itemid>: string): void;

setFroomlePageView("article_detail", "item437");

Use setFroomlePageView(string $pagetype, string $item_id): void;

setFroomlePageView("article_detail", "item437");

Page Visit

A page visit is the viewing of a generic page that cannot be associated with a single item.

Typical examples include:

  • home page

  • category or section page

  • search results page

Page visits help provide context when no specific item is in focus.

  • HTML

  • Javascript

  • PHP

<script data-froomle-page-visit="home"></script>
setFroomlePageVisit("home");
setFroomlePageVisit("home");

Request Domain

Allows you to configure a custom request domain for recommendation calls.

Some ad blockers may block requests to external or unfamiliar URLs, which can prevent recommendations from loading. To avoid this, you may reroute Froomle traffic through a CNAME in your own DNS setup.

Using this parameter, you can set the domain to which all recommendation requests should be redirected.

  • HTML

  • Javascript

  • PHP

Use data-froomle-requestdomain to override the default request domain.

<script data-froomle-requestdomain="mydomain.com"></script>

setFroomleRequestDomain(domain_name: string): void

setFroomleRequestDomain("my.custom.domain");

setFroomleRequestDomain(string $domain): void

setFroomleRequestDomain("my.custom.domain");

Recommendations

Recommendation Placeholder

To mark an element as a recommendation container, add the data-froomle-reco="<list_name>" attribute. Here the list_name is the list the recommendation should use.

  • HTML

  • Javascript

  • PHP

<div data-froomle-reco="recommeded_for_you">
  <img />
  <h1></h1>
</div>
class MyElement extends HTMLElement {
    constructor() {
        super();
        this.dataset.froomleReco = "recommended_for_you";
    }
}
<?php
echo '<div data-froomle-reco="recommeded_for_you">
  <img />
  <h1></h1>
</div>';

Recommendation Parameters

To populate an element attribute using recommendation item data, use: data-froomle-param-<parameterName>="<itemField>"

This works with any valid HTML attribute, including custom data-* attributes.

Attributes used by frameworks (e.g., React props, Vue directives) are not HTML attributes and therefore will not work.
On recommendation, they override the original value set.

Example

  • HTML

  • Javascript

  • PHP

<div data-froomle-reco="recommended_for_you">
  <img data-froomle-param-src="images[0]" />
  <h1></h1>
</div>
class MyElement extends HTMLElement {
    constructor() {
        super();
        this.dataset.froomleReco = "recommended_for_you";

        const image = document.createElement('img');
        this.appendChild(image);
        image.dataset.froomleRecoParamSrc = "images[0]";

        const title = document.createElement('h1');
        this.appendChild(title);
    }
}
<?php
echo '<div data-froomle-reco="recommended_for_you">
<img data-froomle-param-src="images[0]" />
<h1></h1>
</div>';

Recommendation Item

{
  "recoitem": {
    "item_id": "item69420",
    "images": ["https://imageurl.com/img.png"],
    "title": "Reco item Title",
    "uri": "some_uri"
  }
}

Result

<div data-froomle-reco="recommended_for_you">
  <img src="https://imageurl.com/img.png" />
  <h1></h1>
</div>

Inner Content

To insert text content instead of setting an attribute, use:

data-froomle-param-inner="<itemField>"

  • HTML

  • Javascript

  • PHP

<div data-froomle-reco="sports_list">
  <img data-froomle-param-src="images[0]" />
  <h1 data-froomle-param-inner="title"></h1>
</div>
class MyElement extends HTMLElement {
    constructor() {
        super();
        this.dataset.froomleReco = "recommended_for_you";

        const image = document.createElement('img');
        this.appendChild(image);
        image.dataset.froomleRecoParamSrc = "images[0]";

        const title = document.createElement('h1');
        this.appendChild(title);
        title.dataset.froomleParamInner = "title";
    }
}
<?php
echo '<div data-froomle-reco="sports_list">
<img data-froomle-param-src="images[0]" />
<h1 data-froomle-param-inner="title"></h1>
</div>';

recommendation item

{
  "recoitem": {
    "item_id": "item69420",
    "images": ["https://imageurl.com/img.png"],
    "title": "Reco item Title",
    "uri" : "some_uri"
  }
}

result

<div data-froomle-reco="sports_list">
  <img src="https://imageurl.com/img.png" />
  <h1>Reco item Title</h1>
</div>
All data-froomle-param-* attributes must be within the subtree of an element containing data-froomle-reco.

Recommendation Filters

To indicate that a recommendation must belong to a specific category or type, add the attribute:

data-froomle-filter-<itemField>="<value>"

This attribute is used in addition to the data-froomle-reco attribute. Example:

  • HTML

  • Javascript

  • PHP

<div data-froomle-reco="recommended_for_you"
     data-froomle-reco-filter-articletype="sports">

</div>
class MyElement extends HTMLElement {
    constructor() {
        super();
        this.dataset.froomleReco = "recommended_for_you";
        this.dataset.froomleRecoFilterArticletype = "sports";
    }
}
<?php
echo '<div data-froomle-reco="recommended_for_you"
     data-froomle-reco-filter-articletype="sports">

</div>';

will return a recommendation:

{
  "recoitem": {
    "title": "some article title",
    "image": "someurl",
    "articletype": "sports"
  }
}

where the articletype of the recommendation will always be sports.


Item IDs

It is strongly recommended to add item IDs to your own content elements (e.g., articles). These item IDs improve recommendation quality and analytics visible in the Froomle dashboards.

Use the attribute:

data-froomle-id="<item_id>"

Example:

  • HTML

  • Javascript

  • PHP

<div class="my-article" data-froomle-id="article_id">
    <h2>Article Title</h2>
    <img src="article_image_link"/>
</div>
class MyElement extends HTMLElement {
    constructor() {
        super();
        this.dataset.froomleId = "article_id";

        this.classList.add('my-article');
        this.innerHTML = '<h2>Article Title</h2> <img src="article_image_link"/>'

    }
}
<?php
echo '<div class="my-article" data-froomle-id="article_id">
    <h2>Article Title</h2>
    <img src="article_image_link"/>
</div>';

Ordering Sections

You can reorder sections on your page based on aggregated recommendation signals.

Ordering Element

To mark a parent element whose children must be reordered based on recommendations, use:

data-froomle-order="<key>"

The <key> represents the recommendation field on which ordering should be based, and can be a string or a list of strings.

Node structure and non-ordered elements retain their exact position in the DOM.

Elements To Order

Child elements that should participate in the ordering must include:

data-froomle-order-value="<value>"

Here, <value> corresponds to the field value that should be matched against the recommendations.

  • HTML

  • Javascript

  • PHP

<div data-froomle-order="category">
    <div data-froomle-order-value="Politics">Politics content</div>
    <img src="this_will_stay_in_place"/>
    <div data-froomle-order-value="Sports">Sports content</div>
</div>
class MyElement extends HTMLElement {
    constructor() {
        super();
        this.dataset.froomleOrder = "category";

        const div1 = document.createElement('div');
        this.appendChild(div1);
        div1.dataset.froomleOrderValue = "Politics";
        div1.innerHTML = 'Politics Content';

        const image = document.createElement('img');
        this.appendChild(image);
        image.src = "this_will_stay_in_place";

        const div2 = document.createElement('div');
        this.appendChild(div2);
        div2.dataset.froomleOrderValue = "Sports";
        div2.innerHTML = 'Sports Content';
    }
}
<?php
echo '<div data-froomle-order="category">
    <div data-froomle-order-value="Politics">Politics content</div>
    <img src="this_will_stay_in_place"/>
    <div data-froomle-order-value="Sports">Sports content</div>
</div>';

Result if items in category "Sports" are more relevant to the user than items in category "Politics"

<div data-froomle-order="category">
    <div data-froomle-order-value="Sports">Sports content</div>
    <img src="this_will_stay_in_place"/>
    <div data-froomle-order-value="Politics">Politics content</div>
</div>

Category fields may also contain lists of strings.

  • HTML

  • Javascript

  • PHP

<div data-froomle-order="article-categories">
    <div data-froomle-order-value="France">France content</div>
    <img src="this_will_stay_in_place"/>
    <div data-froomle-order-value="Belgium">Belgium content</div>
</div>
class MyElement extends HTMLElement {
    constructor() {
        super();
        this.dataset.froomleOrder = "article-categories";

        const div1 = document.createElement('div');
        this.appendChild(div1);
        div1.dataset.froomleOrderValue = "France";
        div1.innerHTML = 'France Content';

        const image = document.createElement('img');
        this.appendChild(image);
        image.src = "this_will_stay_in_place";

        const div2 = document.createElement('div');
        this.appendChild(div2);
        div2.dataset.froomleOrderValue = "Belgium";
        div2.innerHTML = 'Belgium Content';
    }
}
<?php
echo '<div data-froomle-order="article-categories">
    <div data-froomle-order-value="France">France content</div>
    <img src="this_will_stay_in_place"/>
    <div data-froomle-order-value="Belgium">Belgium content</div>
</div>';

Recommendations

This would be the top recommendations on top of which the ordering is based.

"recos": [
  { "item_id": "item1", "article-categories": ["Sports", "Football", "Belgium"] },
  { "item_id": "item2", "article-categories": ["Politics", "France", "Macron"] },
  { "item_id": "item3", "article-categories": ["Sports", "Football", "France"] },
  { "item_id": "item4", "article-categories": ["Politics", "Belgium", "De Wever"] },
  { "item_id": "item5", "article-categories": ["Sports", "France", "Tennis"] }
]

Result

<div data-froomle-order="article-categories">
    <div data-froomle-order-value="France">France content</div>
    <img src="this_will_stay_in_place"/>
    <div data-froomle-order-value="Belgium">Belgium content</div>
</div>

Advanced

registerOrderCallback(fn: (element: Element, orderedChildren: Element[]) ⇒ void)

When sections are reordered based on recommendations, you may want to apply additional logic or side-effects (e.g. change style). This function allows you to subscribe to the reorder event.

The callback receives:

  • element — the container whose children have been reordered

  • orderedChildren — only the children that were reordered, in their new order

IMPORTANT: orderedChildren contains only the elements that participated in the ordering. To access all children (including those that were not part of the ordering process), use:

example where style gets changed so that:

  1. First item → blue

  2. Second item → red

  3. Third item → green

registerOrderCallback((element, orderedChildren) => {
  const colors = ["blue", "red", "green"];

  orderedChildren.forEach((child, index) => {
    if (index < colors.length) {
      child.style.color = colors[index];
    }
  });
});

PHP Combination with JavaScript

If your implementation requires setting one or more parameters directly in JavaScript, this is fully supported. You can freely combine PHP-based configuration with JavaScript-based configuration.

Example:

<?php

setFroomleEnvironment("my_env");

echo '<script>
  setFroomleUserId("userid");
</script>';