Javascript (Web and CTV)
Configuration guide for the JavaScript SDK, supporting both web browsers and HTML5-based CTV devices in Recurly Engage.
Key benefits
Key details
The JavaScript SDK supports web browsers as well as HTML5-based CTV devices. To install it, see the Recurly Engage JavaScript tag article.
CTV considerations
We recommend the following when you integrate the JavaScript SDK on CTV apps:
- Create a custom device in Settings > Custom Devices. You can define multiple entries, for example
SamsungTV,LGTV, andVidaa. - Create prompts for the custom devices. This gives you control over exactly which prompts are delivered to each CTV platform.
- Specify the custom device that represents the CTV platform in the JavaScript tag. For example:
<script src="..." data-rf-device-type="SamsungTV" /> - Make sure
fetchUserId()is integrated, because user ID retrieval on CTV is often different from a normal desktop or mobile web app. - CTV apps are normally implemented as single-page apps, so using prompts to navigate to specific screens may require a discussion with your development team.
- If you have any questions, contact your Customer Success Manager or [email protected].
Analytics
Recurly Engage has built-in integrations with several analytics services. To report all prompt interaction events in a custom analytics payload instead, implement a callback function in Settings > Custom JS Snippet. The callback is invoked whenever a user interaction occurs.
Callback function example
[TODO: Dev/PO review — possible issue: in the example below, case "dismiss" has no colon, and static appears on a standalone function. Left verbatim.]
/*
This function is called whenever a prompt event occurs, for custom analytics purposes
@param {string} eventName: impression, click, click2, decline, dismiss, timeout, holdout
@param {object} payload: {
activity: "Redfast Prompt Click",
cta: "CTA Button Text",
el: <HTMLElement>,
event_timestamp: "2025-01-01T08:00:00.000Z",
promo_id: "abcd1234-1234-abcd-1234-abcdef123456",
promo_name: "Prompt Name",
user_id: "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
variation_id: "abcd1234-1234-abcd-1234-abcdef123456",
variation_name: "Experiment Name",
}
*/
static onPromptInteraction(eventName, payload) {
switch(eventName) {
case "impression":
myAnalytics.track("Prompt Impression", { "id": payload.promo_id, "name": payload.promo_name });
break;
case "dismiss"
myAnalytics.track("Prompt Dismiss", { "id": payload.promo_id, "name": payload.promo_name });
break;
}
}Google Analytics (GA4) example
static onPromptInteraction(eventName, payload) {
const baseParams = {
promo_id: payload.promo_id,
promo_name: payload.promo_name,
variation_id: payload.variation_id,
variation_name: payload.variation_name,
cta: payload.cta,
activity: payload.activity,
user_id: payload.user_id,
event_timestamp: payload.event_timestamp,
};
switch(eventName) {
case "impression":
gtag("event", "prompt_impression", baseParams);
break;
case "click":
case "click2":
gtag("event", "prompt_click", { ...baseParams, click_type: eventName });
break;
case "decline":
gtag("event", "prompt_decline", baseParams);
break;
case "dismiss":
gtag("event", "prompt_dismiss", baseParams);
break;
case "timeout":
gtag("event", "prompt_timeout", baseParams);
break;
case "holdout":
gtag("event", "prompt_holdout", baseParams);
break;
default:
console.warn("Unknown event:", eventName);
}
}
Segment example
static onPromptInteraction(eventName, payload) {
const properties = {
promo_id: payload.promo_id,
promo_name: payload.promo_name,
variation_id: payload.variation_id,
variation_name: payload.variation_name,
cta: payload.cta,
activity: payload.activity,
event_timestamp: payload.event_timestamp,
};
switch(eventName) {
case "impression":
analytics.track("Prompt Impression", properties);
break;
case "click":
case "click2":
analytics.track("Prompt Click", { ...properties, click_type: eventName });
break;
case "decline":
analytics.track("Prompt Decline", properties);
break;
case "dismiss":
analytics.track("Prompt Dismiss", properties);
break;
case "timeout":
analytics.track("Prompt Timeout", properties);
break;
case "holdout":
analytics.track("Prompt Holdout", properties);
break;
default:
console.warn("Unknown event:", eventName);
}
}
Implementation best practices
These implementation strategies help the Recurly Engage JavaScript snippet start executing as quickly as possible, which minimizes delay on your site.
Load type comparison
The implementation method you choose directly affects execution speed and how soon the script is available on the page.
| Implementation method | Load type | Primary benefit | Use case |
| Minimal Latency | Synchronous | Fastest execution time. The script starts loading and executing immediately, minimizing delay. | Critical: Required when the Engage script must execute before or during initial page rendering (for example, to prevent content flicker or ensure immediate availability). |
| Standard | Deferred/Async | Minimal impact on initial page rendering time (Time to First Paint). | Non-Critical: Acceptable when the Engage script can wait for the page content to load before running. |
Minimal latency implementation
To get the fastest script execution time, we recommend a three-step approach that prioritizes immediate script loading and execution by the browser.
Load the script synchronously
Synchronous loading means scripts load sequentially, one after another, starting with the <head> tag. Don't include the async or defer attributes on the script tag. This forces the browser to pause HTML parsing, fetch the resource, and execute the Recurly Engage script immediately, which is essential for rapid feature initiation.
- preconnect: Initiates an early connection handshake with the Recurly Engage
- preload: Instructs the browser to fetch the script resource immediately with high priority
Example
Replace YOUR_TAG_URL with your specific Recurly Engage script URL.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 1. Resource Hints (preconnect and preload) -->
<link rel="preconnect" href="YOUR_TAG_URL">
<link rel="preload" href="YOUR_TAG_URL/redfast.js" as="script">
<!-- Other meta tags and stylesheets here -->
<!-- 2. Synchronous Recurly Engage Script (placed high in <head>) -->
<script src="YOUR_TAG_URL/redfast.js"></script>
<title>Your Website Title</title>
</head>
<body>
<!-- Page Content -->
</body>
</html>
Updated 3 days ago