Skip to main content

Kameleoon integration with Nuxt

This guide describes how to integrate Nuxt 4 with Kameleoon Web Experimentation, including the steps required to preload the Kameleoon engine with anti-flicker protection and execute the engine.js script after client hydration. This setup ensures optimal performance, visual stability, and compatibility with Nuxt’s rendering lifecycle.

Reference implementations are also available for:

A production-ready Nuxt 4 integration is available here:

https://github.com/Kameleoon/setup-engine-nuxt-4

Before using it, ensure that you replace the sitecode value in integrations/Kameleoon/sitecode.ts

note

Depending on the creation date of your Kameleoon project, your scripts may be hosted on either kameleoon.eu or kameleoon.io.
Always use the domain provided in your project settings within the Kameleoon App.


Overview

Workflow

PhaseWhat HappensComponent
SSR RenderingPreload link and anti-flicker CSS are injectedKameleoonHead.vue
Client HydrationVue hydrates the DOM with no mismatches
Post HydrationKameleoon engine loads asynchronously and initializesKameleoonScriptLoader.client.vue
Fallback Safe-ExitAnti-flicker CSS removed if the script is slow or failsKameleoonScriptLoader.client.vue

Quick setup

  1. Add the folder integrations/Kameleoon to your Nuxt project.
  2. Import and register both integration components in your layout (recommended: layouts/default.vue).
    See: Usage in default.vue

Components

The integration consists of two Vue components, each executed at a different stage of the Nuxt rendering pipeline:

ComponentExecution ContextPurpose
KameleoonHead.vueServer-side (SSR)Injects the preload directive and anti-flicker CSS before hydration
KameleoonScriptLoader.client.vueClient-side (post hydration)Loads the engine script, removes anti-flicker CSS, and manages timeout

This approach ensures fast page rendering, stable UI behavior, and full compatibility with Nuxt's hydration process.


1. KameleoonHead.vue

KameleoonHead.vue runs exclusively during server-side rendering. It prepares the page for a flicker-free experience by:

  • Injecting anti-flicker CSS during SSR
  • Preloading the Kameleoon engine (engine.js) so the browser fetches it as early as possible
<script setup>
import { SITECODE_SRC } from "../sitecode";

// No process.server checks—Nuxt automatically syncs head between SSR & client
</script>

<template>
<Head>
<!-- preload script early -->
<Link rel="preload" :href="SITECODE_SRC" as="script" fetchpriority="high" />

<!-- anti-flicker CSS -->
<Style id="kameleoonLoadingStyleSheet">
* { visibility: hidden !important; background-image: none !important; background-color: inherit !important;
}
</Style>
</Head>
</template>

See KameleoonHead.vue


2. KameleoonScriptLoader.client.vue

KameleoonScriptLoader.client.vue executes only on the client and after hydration.

Its responsibilities include:

  • Removing the anti-flicker stylesheet once the page is ready
  • Loading Kameleoon’s engine.js dynamically
  • Handling timing and fallback behavior for slow or failed script loading
<script setup>
defineOptions({ name: "KameleoonScriptLoader" });

import { nextTick, onMounted } from "vue";
import { SITECODE_SRC } from "~/integrations/Kameleoon/sitecode";

onMounted(async () => {
await nextTick();

const kameleoonLoadingTimeout = 500;

window.kameleoonQueue = window.kameleoonQueue || [];
window.kameleoonStartLoadTime = Date.now();

window.kameleoonDisplayPage = function (fromEngine) {
if (!fromEngine) {
window.kameleoonTimeout = true;
}
document.getElementById("kameleoonLoadingStyleSheet")?.remove();
};

window.kameleoonDisplayPageTimeOut = setTimeout(window.kameleoonDisplayPage, kameleoonLoadingTimeout);

const alreadyLoaded = document.querySelector(`script[src*="${SITECODE_SRC}"]`);
if (!alreadyLoaded) {
const script = document.createElement("script");
script.src = SITECODE_SRC;
script.async = true;
document.head.appendChild(script);
}
});
</script>

<template>
<!-- nothing rendered -->
</template>

See KameleoonScriptLoader.client.vue

note

The default anti-flicker timeout is 1000 ms. You may adjust kameleoonLoadingTimeout as required.


Usage in default.vue

The example below shows how to use both components in your layout:

<script setup>
import KameleoonHead from "~/integrations/Kameleoon/components/KameleoonHead.vue";
import KameleoonScriptLoader from "~/integrations/Kameleoon/components/KameleoonScriptLoader.client.vue";
</script>

<template>
<!-- SSR: preload + anti-flicker -->
<KameleoonHead />

<!-- Client: load script after hydration -->
<KameleoonScriptLoader />

<!-- Layout UI -->
<div class="min-h-screen bg-background font-inter">
<Navigation />

<main class="container mx-auto px-4 py-8">
<NuxtPage />
</main>
</div>
</template>

See default.vue


Key takeaways

  • Prevents hydration mismatch warnings
  • Ensures a flicker-free experience prior to Kameleoon initialization
  • Script loads only once, including during SPA navigation
  • Compatible with layouts, pages, dynamic routes, and conditional rendering

With this configuration, your Nuxt application will load and execute Kameleoon reliably, without affecting rendering stability or user experience.