Intelligent Handshake®

Flash of Default Content (FODC) Prevention Adapter

The Flash of Default Content (FODC) Prevention Adapter is a lightweight, on-page snippet that prevents a flash of default content before the Intelligent Handshake runtime completes rendering.

It works alongside the other two Edge SDK components:

  • Runtime (tag.js) - hosted decisioning and rendering engine
  • FODC Prevention Adapter - on-page render guard
  • Page Plan - configuration describing targets and rendering behavior

Mental model:

  • The Runtime Tag decides what to render.
  • The FODC Prevention Adapter ensures it renders cleanly.

Getting Started

  1. Add the FODC Prevention Adapter snippet once per page.
  2. Keep your existing Intelligent Handshake SDK runtime Tag and Page Plan integration.
  3. Call IHFODC.MarkTargetsStealth(theIntelligentHandshakePagePlan); after your Page Plan is defined.
  4. Add IHFODC.RevealTargets(); to your existing pagePlan.onRender handler.
  5. Leave your current ManipulationMode.Start(...) runtime startup logic unchanged.

Overview

The Adapter is designed to be added as a separate on-page layer on top of the standard Intelligent Handshake SDK integration. It does not replace the runtime Tag and it does not replace the Page Plan.

It performs three jobs:

  • Hide target elements before rendering begins
  • Reveal the final rendered elements when rendering completes
  • Fail open through a visibility-aware failsafe if rendering is delayed or unavailable

When to Use It

Use the FODC Prevention Adapter when your page renders dynamic content into visible page slots and you want to prevent a flash from default content to personalized content.

It is especially useful when:

  • default content is visible before the runtime completes
  • the rendered target may appear below the fold
  • a smooth reveal is preferred over visible content flicker

Adapter Snippet

Add the following snippet once per page. This is the complete on-page FODC Prevention Adapter.

<!--
	IH FODC Prevention v1.1.0
	Purpose: Prevent flash of default content before Intelligent Handshake renders.
	Safe to include once per page.
-->
<style>
	.ih-stealth { opacity: 0; }
	@media (prefers-reduced-motion: no-preference) {
		.ih-reveal { transition: opacity .18s ease-out; }
	}
</style>
<script>
(function (window, document) {
	"use strict";
	if (window.IHFODC && window.IHFODC.Initialized) return;
	var IHFODC = window.IHFODC || {};
	IHFODC.Version = "1.1.0";
	IHFODC.Initialized = true;
	IHFODC.State = { revealed: false, failsafeTimer: null };
	IHFODC.Trace = function () {
		if (window.intelligenthandshake &&
			window.intelligenthandshake.Trace &&
			window.intelligenthandshake.Trace.CheckPoint) {
			window.intelligenthandshake.Trace.CheckPoint.apply(
				window.intelligenthandshake.Trace, arguments
			);
		}
	};
	IHFODC.GetTargets = function (ep) {
		var out = [], seen = new Set();
		if (!ep || !Array.isArray(ep.selectors)) return out;
		ep.selectors.forEach(function (sel) {
			if (typeof sel !== "string" || !sel.trim()) return;
			try {
				document.querySelectorAll(sel).forEach(function (el) {
					if (!seen.has(el)) { seen.add(el); out.push(el); }
				});
			} catch (ex) {
				IHFODC.Trace("FODC invalid selector", sel, ex);
			}
		});
		return out;
	};
	IHFODC.MarkTargetsStealth = function (pagePlan) {
		if (!pagePlan || !Array.isArray(pagePlan.elementPlans)) return;
		pagePlan.elementPlans.forEach(function (ep) {
			IHFODC.GetTargets(ep).forEach(function (el) {
				el.classList.add("ih-stealth", "ih-reveal");
			});
		});
	};
	IHFODC.RevealTargets = function () {
		if (IHFODC.State.revealed) return;
		IHFODC.State.revealed = true;
		if (IHFODC.State.failsafeTimer) {
			clearTimeout(IHFODC.State.failsafeTimer);
			IHFODC.State.failsafeTimer = null;
		}
		document.querySelectorAll(".ih-stealth")
			.forEach(function (el) { el.classList.remove("ih-stealth"); });
	};
	IHFODC.GetMM = function () {
		return window.intelligenthandshake && window.intelligenthandshake.ManipulationMode
			? window.intelligenthandshake.ManipulationMode
			: null;
	};
	IHFODC.SdkIsActive = function () {
		var mm = IHFODC.GetMM();
		return !!(mm && mm.isActive);
	};
	IHFODC.SdkHasRendered = function () {
		var mm = IHFODC.GetMM();
		return !!(mm && mm.manipulationModeCalled);
	};
	IHFODC.StartFailsafe = function () {
		if (IHFODC.State.revealed) return;
		var MAX_WAIT = 10000, RETRY_MS = 500, start = Date.now();
		var done = false, visibleSeen = false, retry = null, io = null;
		function cleanup() {
			if (retry) { clearTimeout(retry); retry = null; }
			if (io) { io.disconnect(); io = null; }
		}
		function reveal(reason) {
			if (done || IHFODC.State.revealed) return;
			done = true;
			IHFODC.State.revealed = true;
			document.querySelectorAll(".ih-stealth")
				.forEach(function (el) { el.classList.remove("ih-stealth"); });
			IHFODC.Trace("FODC reveal", reason);
			cleanup();
		}
		function schedule() {
			if (done || IHFODC.State.revealed || retry) return;
			retry = setTimeout(function () {
				retry = null;
				check("retry");
			}, RETRY_MS);
		}
		function check(reason) {
			if (done || IHFODC.State.revealed) return;
			var elapsed = Date.now() - start;
			if (IHFODC.SdkIsActive() && !IHFODC.SdkHasRendered()) {
				if (elapsed < MAX_WAIT) {
					schedule();
					return;
				}
				reveal("timeout_sdk_stalled");
				return;
			}
			if (visibleSeen) {
				reveal("visible");
				return;
			}
			if (elapsed < MAX_WAIT) {
				schedule();
				return;
			}
			reveal("timeout");
		}
		var elements = Array.from(document.querySelectorAll(".ih-stealth"));
		if (!elements.length) return;
		io = new IntersectionObserver(function (entries) {
			for (var i = 0; i < entries.length; i++) {
				if (entries[i].isIntersecting) {
					visibleSeen = true;
					check("visible_observer");
					break;
				}
			}
		}, { root: null, threshold: 0.01 });
		elements.forEach(function (el) { io.observe(el); });
		schedule();
	};
	if (document.readyState === "complete") {
		IHFODC.StartFailsafe();
	} else {
		window.addEventListener("load", function () {
			IHFODC.StartFailsafe();
		}, { once: true });
	}
	window.IHFODC = IHFODC;
})(window, document);
</script>
<!-- IH FODC Prevention Adapter v1.1.0 - End -->

Standard Integration Remains Unchanged

Keep the standard Intelligent Handshake SDK integration unchanged:

  • Keep your existing runtime tag.js install
  • Keep your existing Page Plan structure
  • Keep your existing ManipulationMode.Start(...) runtime startup logic

The Adapter is an additional on-page layer, not a replacement.

Page Plan Requirements

The Adapter expects targetable element plans to use selectors.

{
	selectors: ["#ih-offer-slot"],
	fallbackMode: "Replace",
	fallbackElementID: "ih_dynamic_offer_default",
	segmentMap: [
		{
			score: "H",
			mode: "Replace",
			ElementID: "ih_dynamic_offer_high"
		}
	]
}

The Adapter uses these selectors to determine which visible page elements should be hidden before rendering.

Required Integration Changes

1. Mark targets as stealth

After your existing Page Plan is defined, add:

IHFODC.MarkTargetsStealth(theIntelligentHandshakePagePlan);

2. Reveal targets on render

In your existing onRender handler, add:

IHFODC.RevealTargets();

If you already have custom logic in onRender, keep it and append the reveal call:

onRender: function (pagePlan, score) {
	renderOffer(score.segmentCode);
	IHFODC.RevealTargets();
}

Example

This example shows the FODC Prevention Adapter added on top of a standard runtime Tag and Page Plan integration.

<div id="ih_dynamic_offer_default" style="display:none;">
	Default content
</div>

<div id="ih_dynamic_offer_high" style="display:none;">
	High-value content
</div>

<div id="ih-offer-slot"></div>

<script>
var theIntelligentHandshakePagePlan = {
	actionKey: "YOUR_ACTION_KEY",
	onRender: function (pagePlan, score) {
		IHFODC.RevealTargets();
	},
	elementPlans: [
		{
			selectors: ["#ih-offer-slot"],
			fallbackMode: "Replace",
			fallbackElementID: "ih_dynamic_offer_default",
			segmentMap: [
				{ score: "H", mode: "Replace", ElementID: "ih_dynamic_offer_high" }
			]
		}
	]
};

IHFODC.MarkTargetsStealth(theIntelligentHandshakePagePlan);
</script>

<script src="https://code.intelligenthandshake.com/YOUR_API_KEY/tag.js"></script>

<script>
(function (p) {
	(function c(k) {
		if (window.intelligenthandshake &&
			window.intelligenthandshake.ManipulationMode &&
			window.intelligenthandshake.ManipulationMode.Start) {
			intelligenthandshake.ManipulationMode.Start(p);
		} else if (k < 100) {
			setTimeout(function () { c(k + 1); }, 50);
		}
	})(0);
})(theIntelligentHandshakePagePlan);
</script>

Samples

GlassBox is a set of controlled reference implementations that demonstrate how the Intelligent Handshake (IH) SDK behaves in real-world rendering scenarios. Each sample isolates a specific rendering pattern so you can observe, test, and validate how content transitions from original → optimized → fallback, including how FODC (Flash of Default Content) is handled.

These samples are designed to help you choose the right integration pattern based on your page structure, performance requirements, and tolerance for visual transitions.

  • GlassBox SDK Sample – Basic
    A minimal implementation of the IH SDK with no FODC mitigation. This sample shows the baseline behavior where original content renders first and is then replaced by optimized content. Use this to understand default rendering flow and SDK timing.
  • GlassBox SDK Sample – Above The Fold (Basic)
    Focuses on above-the-fold content without FODC prevention. This demonstrates the visual impact of content replacement in highly visible areas. Use this to evaluate whether FODC mitigation is required for your primary user experience.
  • GlassBox SDK Sample – Above The Fold (With FODC Prevention)
    Demonstrates FODC prevention applied to above-the-fold content. Target elements are held in a controlled “stealth” state until IH rendering completes or a fallback condition is met. Use this pattern for critical, first-impression UI where visual stability is required.
  • GlassBox SDK Sample – Below The Fold (With FODC Prevention)
    Demonstrates FODC prevention for below-the-fold content using visibility detection. Content is only revealed when it enters the viewport or when fallback conditions trigger. Use this to optimize performance and user experience for scroll-based content regions.

As a general guideline:
• Use Basic samples to understand core behavior
• Use Above-the-Fold with FODC Prevention for primary conversion surfaces
• Use Below-the-Fold patterns to balance performance and visual consistency

Behavior

  • Target elements are hidden immediately through .ih-stealth
  • The runtime Tag renders content based on the Page Plan and score
  • onRender calls IHFODC.RevealTargets()
  • If rendering is delayed, the failsafe waits while the SDK is active
  • If rendering stalls, the failsafe reveals on visibility or timeout

Best Practices

  • Include the Adapter once per page
  • Keep selectors specific and stable
  • Always call IHFODC.RevealTargets() in onRender
  • Do not rename the IHFODC namespace
  • Do not remove the failsafe

Troubleshooting

Content never appears

  • Confirm IHFODC.RevealTargets() is called in onRender
  • Confirm the selectors match visible target elements

Flicker still occurs

  • Confirm IHFODC.MarkTargetsStealth(...) runs before runtime rendering begins
  • Confirm selectors target the correct elements

Failsafe triggers too early

  • Confirm the runtime Tag activates normally
  • Confirm the Page Plan is valid and rendering completes
  • Confirm target elements exist before stealth marking begins

Summary

The Flash of Default Content Prevention Adapter is a non-invasive render guard for the Edge SDK. It adds a clean reveal experience without changing the standard runtime integration.

Add it once per page, mark your Page Plan targets as stealth, and reveal those targets from your existing onRender handler.