Skip to Content
DevelopersJavaScript API

JavaScript API

ResultFly campaigns can send key interaction events from the embedded experience to the host website or application. This allows developers to connect ResultFly to analytics systems, CRM platforms, CDPs, tag managers, and custom business logic.

This JavaScript API is not the canonical CDP ingest surface. If you need to push customer facts into ResultFly as governed profile or event data, use the server-to-server CDP ingest APIs instead.

Typical use cases include:

  • sending campaign interaction events to analytics platforms
  • tracking page views, starts, completions, and question answers
  • capturing form submissions generated inside campaigns
  • tracking rewards or coupons received by users
  • measuring campaign funnels and completion rates
  • triggering actions in external systems

ResultFly provides a public JavaScript API designed to expose stable business-level events from embedded campaigns.


Integration Overview

A ResultFly campaign can be embedded into a client website or application. Once embedded, the campaign sends public events to the host environment using one or more supported delivery methods.

These events can be consumed by:

  • analytics tools such as GA4, Segment, or Amplitude
  • tag managers such as Google Tag Manager
  • CRM or CDP integrations
  • custom front-end logic
  • internal event pipelines

All public events follow a stable versioned contract.


LMS Compatibility

ResultFly JavaScript API works well in LMS environments, especially when campaigns are embedded as iframes inside course pages, lesson modules, or learning portals.

For LMS integrations, postMessage is typically the most reliable delivery method because many LMS platforms restrict direct access to host-page JavaScript while still allowing iframe-to-parent communication.

Typical LMS use cases include:

  • tracking learner interaction starts and completions
  • recording question answers for reporting
  • marking lesson engagement or completion based on finished
  • forwarding ResultFly events into SCORM, xAPI, or proprietary LMS tracking layers

When integrating with an LMS, verify that the platform allows:

  • embedded third-party iframe content
  • cross-window messaging with postMessage
  • the ResultFly campaign origin in any relevant allowlist or content security policy

Quick Start

The simplest integration is embedding the campaign and subscribing to ResultFly events.

<div id="resultfly-embed"></div> <script src="https://cdn.resultfly.com/embed.js"></script> <script> window.addEventListener("resultfly:event", function (e) { const evt = e.detail; console.log("ResultFly event:", evt); if (evt.type === "started") { console.log("User started interaction"); } if (evt.type === "finished") { console.log("Interaction finished:", evt.data?.outcome); } if (evt.type === "reward_received") { console.log("Reward received:", evt.data?.reward_title); } }); </script>

Event Delivery Methods

ResultFly supports multiple ways to deliver events to the host page.

Events are emitted as browser events:

resultfly:event

Example:

window.addEventListener("resultfly:event", (e) => { const event = e.detail; });

This method works well with:

  • modern front-end frameworks
  • analytics SDKs
  • tag managers
  • custom event pipelines

2. Callback Integration (optional)

For simple environments a global callback can be used.

window.onResultFlyEvent = function (event) { console.log("ResultFly event:", event); };

If this function exists, ResultFly calls it for each public event.


3. iframe postMessage Integration

If the campaign is embedded as a pure iframe without the ResultFly host script running on the page, events are delivered via postMessage.

Example:

<iframe src="https://campaign.resultfly.com/demo" width="400" height="700"> </iframe> <script> window.addEventListener("message", function (event) { if (!event.data) return; if (event.data.source !== "resultfly") return; const evt = event.data.event; console.log("ResultFly event:", evt); }); </script>

ResultFly always includes source: "resultfly" in postMessage events to simplify filtering.


Event Model

All ResultFly public events follow a unified schema.

type ResultFlyEvent = { type: | "ready" | "page_viewed" | "started" | "finished" | "answered" | "submitted" | "reward_received" | "error" version: "1.0" timestamp: string campaign_id: string session_id?: string page_id?: string component_id?: string component_type?: string data?: Record<string, unknown> }

Notes:

  • session_id is present for interaction-level events and may be omitted for bridge lifecycle events such as ready.
  • page_id identifies the currently visible campaign page.
  • component_id and component_type identify the component that produced the event.
  • data contains event-specific fields only.

Event Categories

ResultFly public events are grouped into three categories.

Lifecycle Events

EventDescription
readyCampaign embed loaded and JavaScript API is ready
page_viewedA campaign page became visible
startedUser started interacting with a game or interactive component
finishedInteraction completed
errorCampaign encountered a runtime or delivery error

Interaction Events

EventDescription
answeredUser answered a quiz or question component
submittedUser submitted a form inside the campaign

Reward Events

EventDescription
reward_receivedUser received a reward or coupon

Event Reference

ready

Triggered when the campaign embed finishes loading and the JavaScript API is available.

{ "type": "ready", "version": "1.0", "timestamp": "2026-03-13T10:00:00.000Z", "campaign_id": "cmp_demo_001", "data": { "sdk_version": "1.0.0", "delivery_methods": ["dom_event", "callback", "postmessage"] } }

page_viewed

Triggered whenever a campaign page becomes visible.

This event fires:

  • when the campaign first loads
  • when navigating between pages inside the campaign
{ "type": "page_viewed", "version": "1.0", "timestamp": "2026-03-13T10:00:01.000Z", "campaign_id": "cmp_demo_001", "session_id": "sess_abc123", "page_id": "welcome_page", "data": { "previous_page_id": null } }

started

Triggered when the user begins interacting with a game or interactive component.

A campaign page may contain multiple interactive elements, and each interaction can generate its own started event.

{ "type": "started", "version": "1.0", "timestamp": "2026-03-13T10:00:05.000Z", "campaign_id": "cmp_demo_001", "session_id": "trivia_quiz_abc123", "component_id": "quiz_1", "component_type": "trivia_quiz", "data": { "game_type": "trivia_quiz", "started_at": "2026-03-13T10:00:05.000Z", "timer": { "enabled": true, "limit_ms": 60000 } } }

finished

Triggered when a user finishes interacting with a game or interactive component.

This is the primary completion event in the JavaScript API and represents the final outcome of the interaction.

{ "type": "finished", "version": "1.0", "timestamp": "2026-03-13T10:01:12.000Z", "campaign_id": "cmp_demo_001", "session_id": "trivia_quiz_abc123", "component_id": "quiz_1", "component_type": "trivia_quiz", "data": { "outcome": "success", "end_reason": "objective_reached", "duration_ms": 67000, "timer": { "enabled": true, "limit_ms": 60000, "elapsed_ms": 67000, "expired": false }, "metrics": { "score": 8, "correct_answers": 8, "completion_percent": 100 } } }

outcome values

ValueMeaning
successUser successfully completed the interaction
failUser failed the objective
quitUser exited before completion
errorInteraction failed due to an error

end_reason values

ValueMeaning
objective_reachedInteraction objective completed
timer_expiredTime limit reached
time_survivedSurvival-based goal completed
out_of_movesUser ran out of moves
manual_exitUser exited interaction
collisionInteraction ended by collision
errorRuntime failure during play
unknownFallback value if cause unknown

answered

Triggered when a user answers a question inside supported quiz or question components.

{ "type": "answered", "version": "1.0", "timestamp": "2026-03-13T10:00:35.000Z", "campaign_id": "cmp_demo_001", "session_id": "trivia_quiz_abc123", "component_id": "quiz_1", "component_type": "trivia_quiz", "data": { "question_id": "q_1", "answer_id": "a_2", "correct": true } }

Notes:

  • correct is included when the component supports correctness evaluation.
  • For non-scored question components, correct may be omitted.

submitted

Triggered when a user submits a form inside the campaign.

{ "type": "submitted", "version": "1.0", "timestamp": "2026-03-13T10:01:20.000Z", "campaign_id": "cmp_demo_001", "session_id": "sess_abc123", "component_id": "lead_form_1", "component_type": "form", "data": { "field_keys": ["email", "phone", "consent"] } }

Notes:

  • Public JavaScript events do not include raw field values by default.
  • The event is intended for integration, tracking, and workflow triggers.
  • To send lead values to a CRM or backend, use Lead Form Webhooks.

reward_received

Triggered when the user receives a reward.

This event is emitted only after reward allocation is completed and the reward is available to the user.

{ "type": "reward_received", "version": "1.0", "timestamp": "2026-03-13T10:01:25.000Z", "campaign_id": "cmp_demo_001", "session_id": "fortune_wheel_xyz789", "component_id": "wheel_1", "component_type": "fortune_wheel", "data": { "reward_id": "rw_123", "reward_type": "coupon", "reward_title": "10% OFF", "coupon_code": "SAVE10" } }

error

Triggered when the campaign encounters a runtime or delivery error relevant to the host integration.

{ "type": "error", "version": "1.0", "timestamp": "2026-03-13T10:01:30.000Z", "campaign_id": "cmp_demo_001", "session_id": "fortune_wheel_xyz789", "component_id": "wheel_1", "component_type": "fortune_wheel", "data": { "code": "reward_pool_empty", "message": "No rewards available" } }

Analytics Integration Example

Example using dataLayer for Google Tag Manager.

window.addEventListener("resultfly:event", function (e) { const evt = e.detail; window.dataLayer = window.dataLayer || []; if (evt.type === "page_viewed") { window.dataLayer.push({ event: "resultfly_page_viewed", campaign_id: evt.campaign_id, session_id: evt.session_id, page_id: evt.page_id }); } if (evt.type === "started") { window.dataLayer.push({ event: "resultfly_started", campaign_id: evt.campaign_id, session_id: evt.session_id, component_id: evt.component_id, component_type: evt.component_type }); } if (evt.type === "finished") { window.dataLayer.push({ event: "resultfly_finished", campaign_id: evt.campaign_id, session_id: evt.session_id, component_id: evt.component_id, component_type: evt.component_type, outcome: evt.data?.outcome, end_reason: evt.data?.end_reason }); } if (evt.type === "reward_received") { window.dataLayer.push({ event: "resultfly_reward_received", campaign_id: evt.campaign_id, session_id: evt.session_id, reward_id: evt.data?.reward_id, reward_type: evt.data?.reward_type }); } });

Callback Example

window.onResultFlyEvent = function (evt) { if (evt.type === "submitted") { console.log("Form submitted:", evt.component_id); } if (evt.type === "reward_received") { console.log("Reward:", evt.data?.reward_title); } };

postMessage Example

const RESULTFLY_ORIGIN = "https://campaign.resultfly.com"; window.addEventListener("message", function (event) { if (event.origin !== RESULTFLY_ORIGIN) return; if (event.data?.source !== "resultfly") return; const evt = event.data.event; if (evt.type === "finished") { console.log("Finished with outcome:", evt.data?.outcome); } });

Security Notes

When using postMessage, validate the message origin.

const RESULTFLY_ORIGIN = "https://campaign.resultfly.com"; window.addEventListener("message", function (event) { if (event.origin !== RESULTFLY_ORIGIN) return; if (event.data?.source !== "resultfly") return; const evt = event.data.event; });

Versioning

ResultFly uses a versioned public JavaScript event contract.

  • Current version: 1.0
  • New fields may be added inside data
  • Existing documented fields will not change without introducing a new version

Integrations should rely only on documented event names and documented fields.


Support

For integration assistance contact:

support@resultfly.com