How Crazy Egg Works
Crazy Egg is a visual analytics platform that captures how visitors interact with your pages through heatmaps, scroll maps, click maps, session recordings, and built-in A/B testing. Instead of telling you that 73% of visitors left your page, Crazy Egg shows you that they all clicked a static image expecting it to be a button.
The data collection model is snapshot-based. You create a "snapshot" for a specific URL (or URL pattern), and Crazy Egg begins recording visitor interactions on that page. The JavaScript SDK captures mouse coordinates, click positions, scroll depth, viewport dimensions, and DOM state. This data is processed server-side into visual overlays: heatmaps that show click density, scroll maps that show how far visitors travel, and confetti views that segment clicks by referrer, device, or custom variables.
Session recordings work differently from snapshots. Once enabled, Crazy Egg records full visitor sessions across pages by capturing DOM mutations, scroll events, mouse movements, and click actions. These recordings are stored as lightweight event streams (not video), which keeps the file size small and allows playback at variable speed.
The A/B testing engine uses the same JavaScript SDK. When a test is active, Crazy Egg intercepts the page render, applies the variant modifications to the DOM, and tracks which variant each visitor sees. Conversions are measured against goals you define: clicks on a specific element, visits to a URL, or form submissions.
Installing the Crazy Egg Script
Add the Crazy Egg tracking script before the closing </head> tag. Your account number is in the script URL provided in your Crazy Egg dashboard under Tracking Code.
<script type="text/javascript" src="//script.crazyegg.com/pages/scripts/XXXX/XXXX.js" async="async"></script>
The XXXX/XXXX path is your unique account identifier. The script is approximately 20 KB and loads asynchronously, so it does not block page rendering.
Loading via Google Tag Manager
Create a Custom HTML tag in GTM with the following code. Set it to fire on All Pages.
<script type="text/javascript">
(function () {
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = '//script.crazyegg.com/pages/scripts/XXXX/XXXX.js';
var entry = document.getElementsByTagName('script')[0];
entry.parentNode.insertBefore(script, entry);
})();
</script>
Verifying Installation
Open your site in Chrome, then open DevTools (F12) and go to the Network tab. Filter by crazyegg. You should see the script loading successfully (200 status). You can also type CE2 in the console. If it returns an object, the SDK is loaded.
In the Crazy Egg dashboard, navigate to Snapshots and check that your page's snapshot shows "Collecting Data." New snapshots typically begin receiving data within 5 minutes of installation.
Core Visual Analytics
Heatmaps
Heatmaps aggregate click data across all visitors into a color-coded overlay. Red indicates high click density, blue indicates low. Crazy Egg generates heatmaps automatically for any page with an active snapshot.
To control which pages get tracked, you can configure snapshots by exact URL, URL pattern with wildcards, or regex:
- Exact:
https://example.com/pricing - Wildcard:
https://example.com/blog/* - Regex:
https://example\.com/products/[0-9]+
Scroll Maps
Scroll maps show what percentage of visitors reached each vertical position on the page. A sharp drop-off at a specific point tells you that most visitors never see content below that line.
Crazy Egg measures scroll depth in percentage increments. The data powers a gradient overlay on your page: bright colors at the top (100% of visitors see this), fading to dark at the bottom. The exact percentages are shown in the sidebar.
Confetti Reports
Confetti view shows individual clicks as colored dots, each representing a single click. The color coding segments clicks by a dimension you choose:
- Referral source (Google, Facebook, Direct)
- Search term
- New vs. returning visitor
- Device type (desktop, tablet, mobile)
- Operating system
- Browser
- Day of week
- Time of day
This granularity reveals behavioral differences between segments. For example, mobile visitors might click a hamburger menu icon that desktop visitors ignore entirely.
Session Recordings
Recordings capture the full visitor experience. You can watch mouse movement, clicks, scrolling, typing (with sensitive fields masked), page transitions, and rage clicks (rapid repeated clicks on the same area).
Filter recordings by:
Page URL, date range, duration, country, device type,
referrer, new vs. returning, and custom user data
Crazy Egg automatically tags recordings that contain rage clicks, dead clicks (clicks on non-interactive elements), or error events.
Custom Event Tracking and User Data
Setting User Variables
Use the CE2 object to pass custom data that appears in confetti reports and recording filters:
// Set custom variables (up to 5)
CE2.set(1, 'Premium'); // Variable 1: Plan type
CE2.set(2, 'jane@acme.com'); // Variable 2: User email
CE2.set(3, 'Enterprise'); // Variable 3: Segment
CE2.set(4, '2025-06-15'); // Variable 4: Signup date
CE2.set(5, 'Onboarding'); // Variable 5: Lifecycle stage
Variables must be set after the Crazy Egg script loads. To safely handle the timing, wrap calls in a check:
function setCrazyEggVars() {
if (typeof CE2 !== 'undefined') {
CE2.set(1, currentUser.plan);
CE2.set(2, currentUser.email);
} else {
setTimeout(setCrazyEggVars, 500);
}
}
setCrazyEggVars();
Tracking Virtual Pageviews in SPAs
For single-page applications where URL changes do not trigger full page reloads, notify Crazy Egg of navigation events:
// After a client-side route change
if (typeof CE2 !== 'undefined') {
CE2.virtualPageview();
}
In React with React Router:
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
function useCrazyEggTracking() {
const location = useLocation();
useEffect(() => {
if (typeof CE2 !== 'undefined' && typeof CE2.virtualPageview === 'function') {
CE2.virtualPageview();
}
}, [location.pathname]);
}
A/B Testing
Crazy Egg includes a visual A/B testing editor. You select an element on the page, modify it (change text, color, position, visibility), and Crazy Egg serves the modified version to a percentage of visitors.
Programmatic Variant Assignment
For more complex tests that require code changes, use the Crazy Egg Goals API to track conversions:
// Track a conversion goal (e.g., form submission)
if (typeof CE2 !== 'undefined') {
CE2.goal('signup_form_completed');
}
Setting Up a Test
- Create a new A/B test in the Crazy Egg dashboard
- Select the page URL to test
- Use the visual editor to create one or more variants
- Set traffic allocation (e.g., 50/50 split)
- Define the conversion goal (click on element, page visit, or custom goal)
- Launch the test and wait for statistical significance
Crazy Egg calculates statistical significance automatically and marks the winning variant when confidence reaches 95%.
Integration with Other Tools
Forwarding Crazy Egg Insights to GA4
Crazy Egg does not send data to GA4 directly. However, you can use the user variable data to create custom dimensions in GA4 that correspond to Crazy Egg segments:
// Set matching dimensions in both platforms
CE2.set(1, userSegment);
gtag('set', 'user_properties', {
ce_segment: userSegment
});
Using Crazy Egg with GTM Data Layer
Pass data layer values into Crazy Egg variables for consistent segmentation:
window.dataLayer = window.dataLayer || [];
// Listen for data layer events and forward to Crazy Egg
(function() {
var originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
var result = originalPush.apply(this, arguments);
var data = arguments[0];
if (data && data.event === 'user_identified' && typeof CE2 !== 'undefined') {
CE2.set(1, data.user_type);
CE2.set(2, data.user_plan);
}
return result;
};
})();
Exporting Data
Crazy Egg provides CSV exports for heatmap click data and recording metadata. Use these exports to correlate Crazy Egg findings with conversion data from your analytics platform. The export includes click coordinates, element selectors, timestamps, and the visitor's segment data.
Common Errors
| Error | Cause | Fix |
|---|---|---|
| Heatmap shows no data after 24 hours | Snapshot URL does not match the actual page URL (www vs. non-www, HTTP vs. HTTPS) | Edit the snapshot and update the URL to match exactly, including protocol and subdomain |
CE2 is not defined |
Script has not finished loading, or was blocked by ad blocker or CSP | Wrap CE2 calls in a typeof check; add script.crazyegg.com to CSP script-src |
| Recordings show blank white page | CSS/font resources blocked by CORS or CSP on the recording server | Ensure Access-Control-Allow-Origin headers allow Crazy Egg's recording domain |
| A/B test shows flicker (original content flashes before variant loads) | Crazy Egg script loads after the browser paints the original content | Move the Crazy Egg script higher in <head> or add a CSS rule to hide the tested element until the script runs |
| Scroll map cuts off mid-page | Page uses lazy loading that does not render content until scroll | Ensure lazy-loaded content is present in the DOM (even if hidden) when the page loads |
| Heatmap clicks appear offset from elements | Page layout shifted after Crazy Egg captured the snapshot screenshot | Retake the snapshot to capture the current layout |
| Variables not appearing in confetti | CE2.set() called before the SDK finished loading |
Use the polling pattern with setTimeout to wait for CE2 to be defined |
| Recording does not capture iframe content | Crazy Egg cannot record cross-origin iframes | Host iframe content on the same domain, or accept that iframe interactions will not appear in recordings |
| Mobile heatmap is empty | Snapshot only tracks the desktop viewport by default | Create a separate snapshot with the mobile URL or enable responsive tracking in snapshot settings |
| Too many snapshots running, data is thin | Active snapshot limit reached; traffic is split across many snapshots | Pause unused snapshots to concentrate traffic on the ones you are actively analyzing |
Performance Considerations
The Crazy Egg script weighs approximately 20 KB gzipped and loads asynchronously. It does not block the critical rendering path and has minimal impact on Core Web Vitals when loaded with the async attribute.
Session recordings add overhead because the SDK must observe DOM mutations and capture mouse/scroll events. On pages with heavy DOM manipulation (real-time dashboards, chat interfaces), recording can increase CPU usage by 2-5%. If this is a concern, exclude high-activity pages from recordings using URL filters in the Crazy Egg dashboard.
A/B tests that modify the DOM can cause a flash of original content (FOOC) if the Crazy Egg script loads after the initial paint. To mitigate this:
/* Hide the tested element until Crazy Egg applies the variant */
.ab-test-target {
visibility: hidden;
}
// Crazy Egg will set visibility: visible when the variant is applied
// Add a fallback timeout so the element shows even if the script fails
setTimeout(function () {
var el = document.querySelector('.ab-test-target');
if (el) el.style.visibility = 'visible';
}, 2000);
Limit the number of active snapshots to what you are actively analyzing. Each active snapshot records data independently, and running 50 snapshots when you only review 5 wastes your plan's pageview quota.