Developer

SSR framework coexistence

Integrate Apex with hydrating Nuxt and Next.js storefronts using mutation re-assertion, hydration timing, and explicit lifecycle hooks.

Apex is designed to coexist with storefronts that server-render HTML and then hydrate it in the browser. The SDK mutes its own DOM writes so its observers do not react to Apex work. If React, Vue, or another renderer later restores server HTML over an active treatment, Apex re-applies the affected text, HTML, attribute, or style on the next animation frame.

Inserted and removed nodes are not re-applied by this sentinel. Existing SPA re-evaluation remains the fallback for those structural changes.

Choose when mutations apply

The shop runtime setting spa.applyTiming has two modes:

ModeBehaviorTrade-off
immediateApex applies during the initial render path. If hydration overwrites a treatment, Apex corrects it within about one animation frame.Best chance of a clean first paint; a framework overwrite can still produce a very short correction.
after_hydrationApex waits for hydration before applying DOM mutations. The anti-flicker hide remains active until apply or its existing 1200ms safety cap.Avoids the framework/Apex double render, but the affected element stays hidden while hydration settles. The hydration gate fails open after the configured timeout.

spa.hydrationTimeoutMs controls the hydration fail-open window from 500 to 10000ms and defaults to 3000ms. Configure both values under Installation → Storefront runtime controls → SPA and dynamic page support.

ts
spa: {
  applyTiming: "after_hydration",
  hydrationTimeoutMs: 3000
}

Explicit lifecycle hooks

Use the browser API after the hosted SDK has loaded:

js
window.drip("hold");       // increments the mutation hold counter
window.drip("release");    // decrements it; apply resumes when it reaches zero
window.drip("hydrated");   // declares framework hydration complete
 
// Method equivalents
window.drip.hold();
window.drip.release();
window.drip.hydrated();

Holds are nestable. A forgotten hold fails open after spa.hydrationTimeoutMs, records a performance marker, and logs a warning. hold and release also work when applyTiming is immediate.

If an integration cannot call the API directly, dispatch the equivalent hydration event:

js
document.dispatchEvent(new CustomEvent("drip:hydrated"));

Nuxt 3

Fire the signal from a client plugin after the app mounts:

ts
// plugins/apex-hydrated.client.ts
export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook("app:mounted", () => window.drip?.hydrated?.());
});

Next.js App Router

Mount a tiny client component once in the root layout:

tsx
"use client";
 
import { useEffect } from "react";
 
export function ApexHydrated() {
  useEffect(() => window.drip?.hydrated?.(), []);
  return null;
}

Re-initialize widgets after HTML replacement

An html treatment replaces a subtree. When Apex has to re-apply that HTML after a framework overwrite, event listeners inside the subtree no longer exist. Apex does not automatically re-run variation JavaScript. Instead it dispatches drip:mutation-reapplied on document:

ts
document.addEventListener("drip:mutation-reapplied", (event) => {
  const detail = event.detail;
  if (detail.selector !== "[data-apex-swiper]" || detail.action !== "html") return;
 
  document.querySelectorAll("[data-apex-swiper]").forEach((element) => {
    if (element.swiper) element.swiper.destroy(true, true);
    new Swiper(element, { slidesPerView: 1, loop: true });
  });
});

Event detail contains experimentId, variationId, selector, and action. Keep the handler idempotent because a framework can overwrite the same subtree more than once.

Hydration hooks only control mutation timing. Use the existing setConsent(true|false) API or a configured consent provider for storage and tracking permission. Do not use a consent manager to block the Apex script itself; see Consent integration.