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"); Consent Froomle supports three levels of user consent. These levels determine how recommendations are generated and what type of tracking is allowed. Consent Level 2 — Full Personalization 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. Consent Level 1 — Impression Tracking Only 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. Consent Level 0 — No Tracking (Default) 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: First item → blue Second item → red 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>';