/** * MetaRouter Hero Animation * Embeddable scroll-driven 3D animation for hero section * * Usage: *
* */ (function() { 'use strict'; // ======================================================================== // CONFIGURATION OBJECT - EDIT THIS TO CUSTOMIZE // ======================================================================== const CONFIG = { // Content text: { title: 'The First-Mile Data Layer', subtitle: 'MetaRouter gives the world\'s largest enterprises full control over their customer data, secure, real-time, and privacy-compliant. Remove fragile client-side tags, unify identity, recover lost tracking, and power personalization, AI, and retail media at scale.', primaryButton: { label: 'Get a Demo', url: 'https://www.metarouter.io/lp/get-started' }, videoButton: { labelDesktop: 'MetaRouter in 90 Seconds', labelMobile: '90 Second Demo', youtubeId: 'qhCYeiU9B7A' } }, // Color Palette colors: { primary: '#338cf1', secondary: '#2d3282', darkPurple1: '#1c1134', darkPurple2: '#161322', darkPurple3: '#0f0d18', background: '#13101d', coral: '#FEA594', white: '#ffffff', glowBlue: '#338cf1', rimLight: '#4da6ff' }, // Responsive Breakpoints breakpoints: { mobile: 768, tablet: 1024, desktop: 1440 }, // Performance Settings performance: { targetFPS: 60, particleCount: { desktop: 200, tablet: 100, mobile: 50 }, enableParallax: true, enable3D: true }, // Animation Timing (in seconds) timing: { stageTransitionDuration: 1.5, totalScrollHeight: 4000, // Height of scroll-jacked section in px idleLoopDuration: 3 }, // Asset Paths assets: { basePath: './assets/', logos: { javascript: 'js-icon.svg', mobile: 'mobile-icon.svg', server: 'server-icon.svg', meta: 'meta-icon.svg', snowflake: 'snowflake-icon.svg', tradedesk: 'tradedesk-icon.svg', placeholder: 'placeholder-logo.svg' } }, // CDN URLs cdn: { three: 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js', gsap: 'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js', scrollTrigger: 'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js' }, // Dev Mode (auto-detected) devMode: window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' }; // ======================================================================== // MAIN CLASS // ======================================================================== class MetaRouterHero { constructor(containerId) { this.container = document.getElementById(containerId); if (!this.container) { console.error(`MetaRouter Hero: Container #${containerId} not found`); return; } this.isInitialized = false; this.isMobile = false; this.isTablet = false; this.isDesktop = false; this.currentStage = 0; this.dependencies = { three: false, gsap: false, scrollTrigger: false }; // Performance monitoring this.fps = 0; this.frameCount = 0; this.lastFPSUpdate = performance.now(); // Detect reduced motion preference this.prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; this.init(); } // ==================================================================== // INITIALIZATION // ==================================================================== async init() { this.log('Initializing MetaRouter Hero Animation...'); // Detect device type this.detectDeviceType(); // Build DOM structure first (so we have something to show) this.buildDOM(); // Load dependencies await this.loadDependencies(); // Initialize appropriate rendering mode if (this.isMobile && !CONFIG.performance.enable3D) { this.initMobileFallback(); } else { this.init3DScene(); } // Set up interactions this.setupEventListeners(); // Start animation loop this.animate(); // Initialize scroll trigger this.initScrollTrigger(); this.isInitialized = true; this.log('Initialization complete!'); } detectDeviceType() { const width = window.innerWidth; this.isMobile = width < CONFIG.breakpoints.mobile; this.isTablet = width >= CONFIG.breakpoints.mobile && width < CONFIG.breakpoints.desktop; this.isDesktop = width >= CONFIG.breakpoints.desktop; this.log(`Device detected: ${this.isMobile ? 'Mobile' : this.isTablet ? 'Tablet' : 'Desktop'} (${width}px)`); } async loadDependencies() { this.log('Loading dependencies from CDN...'); const loadScript = (url, name) => { return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = url; script.onload = () => { this.dependencies[name] = true; this.log(`✓ ${name} loaded`); resolve(); }; script.onerror = () => { this.log(`✗ ${name} failed to load`); reject(new Error(`Failed to load ${name}`)); }; document.head.appendChild(script); }); }; try { // Load Three.js first await loadScript(CONFIG.cdn.three, 'three'); // Load GSAP and ScrollTrigger in parallel await Promise.all([ loadScript(CONFIG.cdn.gsap, 'gsap'), loadScript(CONFIG.cdn.scrollTrigger, 'scrollTrigger') ]); // Register ScrollTrigger plugin if (window.gsap && window.ScrollTrigger) { gsap.registerPlugin(ScrollTrigger); } } catch (error) { this.log('Failed to load dependencies:', error); // Fallback to simpler animation if deps fail this.initMobileFallback(); } } // ==================================================================== // DOM CONSTRUCTION // ==================================================================== buildDOM() { this.container.innerHTML = ''; this.container.style.cssText = ` position: relative; width: 100%; min-height: 100vh; background: ${CONFIG.colors.background}; overflow: hidden; `; // Create canvas container for 3D scene this.canvasContainer = document.createElement('div'); this.canvasContainer.id = 'mr-canvas-container'; this.canvasContainer.style.cssText = ` position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; `; this.container.appendChild(this.canvasContainer); // Create content overlay this.contentOverlay = document.createElement('div'); this.contentOverlay.id = 'mr-content-overlay'; this.contentOverlay.style.cssText = ` position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; padding: 80px 20px; pointer-events: none; `; this.container.appendChild(this.contentOverlay); // Build text content const contentWrapper = document.createElement('div'); contentWrapper.style.cssText = ` max-width: 900px; text-align: center; margin-bottom: 40px; `; const title = document.createElement('h1'); title.textContent = CONFIG.text.title; title.style.cssText = ` font-family: 'IBM Plex Sans', sans-serif; font-size: ${this.isMobile ? '36px' : '56px'}; font-weight: 700; color: ${CONFIG.colors.white}; margin-bottom: 24px; line-height: 1.2; opacity: 0; transform: translateY(30px); `; contentWrapper.appendChild(title); const subtitle = document.createElement('p'); subtitle.textContent = CONFIG.text.subtitle; subtitle.style.cssText = ` font-family: 'IBM Plex Sans', sans-serif; font-size: ${this.isMobile ? '16px' : '18px'}; font-weight: 400; color: rgba(255, 255, 255, 0.8); line-height: 1.6; margin-bottom: 0; opacity: 0; transform: translateY(30px); `; contentWrapper.appendChild(subtitle); this.contentOverlay.appendChild(contentWrapper); // Build CTA buttons const buttonContainer = document.createElement('div'); buttonContainer.style.cssText = ` display: flex; gap: 16px; flex-wrap: wrap; justify-content: center; pointer-events: auto; opacity: 0; transform: translateY(30px); `; // Primary CTA button const primaryBtn = document.createElement('a'); primaryBtn.href = CONFIG.text.primaryButton.url; primaryBtn.textContent = CONFIG.text.primaryButton.label; primaryBtn.target = '_blank'; primaryBtn.rel = 'noopener noreferrer'; primaryBtn.style.cssText = ` font-family: 'IBM Plex Sans', sans-serif; font-size: 16px; font-weight: 600; color: ${CONFIG.colors.darkPurple3}; background: ${CONFIG.colors.coral}; padding: 16px 32px; border-radius: 999px; text-decoration: none; transition: all 0.3s ease; cursor: pointer; border: none; box-shadow: 0 4px 20px rgba(254, 165, 148, 0.3); `; primaryBtn.addEventListener('mouseenter', () => { primaryBtn.style.transform = 'scale(1.05)'; primaryBtn.style.boxShadow = '0 6px 30px rgba(254, 165, 148, 0.5)'; }); primaryBtn.addEventListener('mouseleave', () => { primaryBtn.style.transform = 'scale(1)'; primaryBtn.style.boxShadow = '0 4px 20px rgba(254, 165, 148, 0.3)'; }); buttonContainer.appendChild(primaryBtn); // Video button const videoBtn = document.createElement('button'); videoBtn.textContent = this.isMobile ? CONFIG.text.videoButton.labelMobile : CONFIG.text.videoButton.labelDesktop; videoBtn.style.cssText = ` font-family: 'IBM Plex Sans', sans-serif; font-size: 16px; font-weight: 600; color: ${CONFIG.colors.white}; background: transparent; padding: 16px 32px; border-radius: 999px; border: 2px solid ${CONFIG.colors.primary}; text-decoration: none; transition: all 0.3s ease; cursor: pointer; box-shadow: 0 4px 20px rgba(51, 140, 241, 0.2); `; videoBtn.addEventListener('click', () => this.openVideoLightbox()); videoBtn.addEventListener('mouseenter', () => { videoBtn.style.transform = 'scale(1.05)'; videoBtn.style.background = 'rgba(51, 140, 241, 0.1)'; videoBtn.style.boxShadow = '0 6px 30px rgba(51, 140, 241, 0.4)'; }); videoBtn.addEventListener('mouseleave', () => { videoBtn.style.transform = 'scale(1)'; videoBtn.style.background = 'transparent'; videoBtn.style.boxShadow = '0 4px 20px rgba(51, 140, 241, 0.2)'; }); buttonContainer.appendChild(videoBtn); this.contentOverlay.appendChild(buttonContainer); // Store references for animation this.domElements = { title, subtitle, buttonContainer }; // Animate in after a short delay setTimeout(() => { if (window.gsap) { gsap.to(title, { opacity: 1, y: 0, duration: 1, ease: 'power3.out' }); gsap.to(subtitle, { opacity: 1, y: 0, duration: 1, delay: 0.2, ease: 'power3.out' }); gsap.to(buttonContainer, { opacity: 1, y: 0, duration: 1, delay: 0.4, ease: 'power3.out' }); } else { title.style.opacity = '1'; title.style.transform = 'translateY(0)'; subtitle.style.opacity = '1'; subtitle.style.transform = 'translateY(0)'; buttonContainer.style.opacity = '1'; buttonContainer.style.transform = 'translateY(0)'; } }, 500); } // ==================================================================== // 3D SCENE SETUP // ==================================================================== init3DScene() { if (!window.THREE) { this.log('Three.js not loaded, falling back to 2D'); this.initMobileFallback(); return; } this.log('Initializing 3D scene...'); // Create scene this.scene = new THREE.Scene(); this.scene.fog = new THREE.FogExp2(CONFIG.colors.background, 0.02); // Create camera const aspect = window.innerWidth / window.innerHeight; this.camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000); this.camera.position.z = 5; // Create renderer this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, powerPreference: 'high-performance' }); this.renderer.setSize(window.innerWidth, window.innerHeight); this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); this.renderer.setClearColor(CONFIG.colors.background, 1); this.canvasContainer.appendChild(this.renderer.domElement); // Add lights this.setupLights(); // Create scene objects this.createSceneObjects(); // Store initial mouse position for parallax this.mouse = { x: 0, y: 0 }; } setupLights() { // Ambient light const ambientLight = new THREE.AmbientLight(0xffffff, 0.4); this.scene.add(ambientLight); // Rim light (blue glow from behind) const rimLight = new THREE.DirectionalLight(CONFIG.colors.rimLight, 1.5); rimLight.position.set(0, 0, -5); this.scene.add(rimLight); // Key light (from front-right) const keyLight = new THREE.DirectionalLight(CONFIG.colors.glowBlue, 0.8); keyLight.position.set(5, 5, 5); this.scene.add(keyLight); // Fill light (soft from left) const fillLight = new THREE.DirectionalLight(0xffffff, 0.3); fillLight.position.set(-5, 0, 5); this.scene.add(fillLight); } createSceneObjects() { this.sceneObjects = { sources: [], processor: null, destinations: [], particles: null, dataStreams: [] }; // Create particle system this.createParticleSystem(); // Create data sources (Capture stage) this.createDataSources(); // Create central processor (Process stage) this.createProcessor(); // Create destinations (Deliver stage) this.createDestinations(); // Create data streams this.createDataStreams(); } createParticleSystem() { const particleCount = this.isMobile ? CONFIG.performance.particleCount.mobile : this.isTablet ? CONFIG.performance.particleCount.tablet : CONFIG.performance.particleCount.desktop; const geometry = new THREE.BufferGeometry(); const positions = new Float32Array(particleCount * 3); const colors = new Float32Array(particleCount * 3); const color1 = new THREE.Color(CONFIG.colors.primary); const color2 = new THREE.Color(CONFIG.colors.secondary); for (let i = 0; i < particleCount; i++) { const i3 = i * 3; // Random positions in a sphere const radius = 10 + Math.random() * 20; const theta = Math.random() * Math.PI * 2; const phi = Math.acos((Math.random() * 2) - 1); positions[i3] = radius * Math.sin(phi) * Math.cos(theta); positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta); positions[i3 + 2] = radius * Math.cos(phi) - 10; // Gradient between two colors const mixedColor = color1.clone().lerp(color2, Math.random()); colors[i3] = mixedColor.r; colors[i3 + 1] = mixedColor.g; colors[i3 + 2] = mixedColor.b; } geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); const material = new THREE.PointsMaterial({ size: this.isMobile ? 0.05 : 0.08, vertexColors: true, transparent: true, opacity: 0.6, blending: THREE.AdditiveBlending }); this.sceneObjects.particles = new THREE.Points(geometry, material); this.scene.add(this.sceneObjects.particles); } createDataSources() { // Three data sources positioned in a horizontal line const sourcePositions = [ { x: -3, y: 1, z: 0 }, // JavaScript { x: 0, y: 1, z: 0 }, // Mobile { x: 3, y: 1, z: 0 } // Server ]; sourcePositions.forEach((pos, index) => { const geometry = new THREE.BoxGeometry(0.8, 0.8, 0.8); const material = new THREE.MeshPhysicalMaterial({ color: CONFIG.colors.primary, metalness: 0.7, roughness: 0.2, transparent: true, opacity: 0.8, envMapIntensity: 1, clearcoat: 1, clearcoatRoughness: 0.1 }); const cube = new THREE.Mesh(geometry, material); cube.position.set(pos.x, pos.y, pos.z); cube.userData = { type: 'source', index }; this.scene.add(cube); this.sceneObjects.sources.push(cube); }); } createProcessor() { // Central processor - larger glass sphere const geometry = new THREE.SphereGeometry(1, 32, 32); const material = new THREE.MeshPhysicalMaterial({ color: CONFIG.colors.primary, metalness: 0.8, roughness: 0.1, transparent: true, opacity: 0.6, envMapIntensity: 2, clearcoat: 1, clearcoatRoughness: 0, transmission: 0.5, thickness: 0.5 }); this.sceneObjects.processor = new THREE.Mesh(geometry, material); this.sceneObjects.processor.position.set(0, -1, 0); this.sceneObjects.processor.userData = { type: 'processor' }; this.scene.add(this.sceneObjects.processor); } createDestinations() { // Three destinations positioned at the bottom const destPositions = [ { x: -3, y: -3, z: 0 }, // Meta { x: 0, y: -3, z: 0 }, // Snowflake { x: 3, y: -3, z: 0 } // Trade Desk ]; destPositions.forEach((pos, index) => { const geometry = new THREE.CylinderGeometry(0.5, 0.5, 0.8, 32); const material = new THREE.MeshPhysicalMaterial({ color: CONFIG.colors.coral, metalness: 0.6, roughness: 0.3, transparent: true, opacity: 0.8, envMapIntensity: 1, clearcoat: 0.8, clearcoatRoughness: 0.2 }); const cylinder = new THREE.Mesh(geometry, material); cylinder.position.set(pos.x, pos.y, pos.z); cylinder.userData = { type: 'destination', index }; this.scene.add(cylinder); this.sceneObjects.destinations.push(cylinder); }); } createDataStreams() { // Create lines from sources to processor, and processor to destinations const lineMaterial = new THREE.LineBasicMaterial({ color: CONFIG.colors.primary, transparent: true, opacity: 0.4, linewidth: 2 }); // Sources to processor this.sceneObjects.sources.forEach(source => { const points = []; points.push(source.position); points.push(this.sceneObjects.processor.position); const geometry = new THREE.BufferGeometry().setFromPoints(points); const line = new THREE.Line(geometry, lineMaterial); line.userData = { type: 'stream', stage: 'input' }; this.scene.add(line); this.sceneObjects.dataStreams.push(line); }); // Processor to destinations this.sceneObjects.destinations.forEach(dest => { const points = []; points.push(this.sceneObjects.processor.position); points.push(dest.position); const geometry = new THREE.BufferGeometry().setFromPoints(points); const line = new THREE.Line(geometry, lineMaterial); line.userData = { type: 'stream', stage: 'output' }; this.scene.add(line); this.sceneObjects.dataStreams.push(line); }); } // ==================================================================== // MOBILE FALLBACK (2D) // ==================================================================== initMobileFallback() { this.log('Initializing mobile fallback (2D mode)...'); // Simple CSS animation fallback this.canvasContainer.innerHTML = `
`; } // ==================================================================== // SCROLL TRIGGER SETUP // ==================================================================== initScrollTrigger() { if (!window.gsap || !window.ScrollTrigger) { this.log('GSAP/ScrollTrigger not loaded, skipping scroll effects'); return; } this.log('Setting up scroll trigger...'); // Pin the hero section ScrollTrigger.create({ trigger: this.container, start: 'top top', end: `+=${CONFIG.timing.totalScrollHeight}`, pin: true, scrub: 1, onUpdate: (self) => { this.updateAnimationStage(self.progress); } }); } updateAnimationStage(progress) { // Map scroll progress (0-1) to animation stages (0-6) const stageProgress = progress * 6; const newStage = Math.floor(stageProgress); if (newStage !== this.currentStage) { this.currentStage = newStage; this.onStageChange(newStage); } this.updateSceneForProgress(stageProgress); } onStageChange(stage) { this.log(`Stage changed to: ${stage}`); // Update dev indicator if (CONFIG.devMode) { const stageEl = document.getElementById('stage'); if (stageEl) stageEl.textContent = stage; } } updateSceneForProgress(progress) { if (!this.scene) return; // Animate scene objects based on scroll progress // Stage 0-1: Sources appear if (progress < 1) { this.sceneObjects.sources.forEach((source, i) => { source.scale.setScalar(Math.max(0, progress - i * 0.2)); }); } // Stage 1-2: Processor appears if (progress >= 1 && progress < 2) { const p = progress - 1; this.sceneObjects.processor.scale.setScalar(p); } // Stage 2-3: Destinations appear if (progress >= 2 && progress < 3) { const p = progress - 2; this.sceneObjects.destinations.forEach((dest, i) => { dest.scale.setScalar(Math.max(0, p - i * 0.2)); }); } // Stage 3-4: Streams appear if (progress >= 3) { this.sceneObjects.dataStreams.forEach(stream => { stream.material.opacity = Math.min(0.8, (progress - 3) * 0.4); }); } // Continuous rotation of objects this.sceneObjects.sources.forEach(source => { source.rotation.y += 0.005; }); if (this.sceneObjects.processor) { this.sceneObjects.processor.rotation.y += 0.01; } this.sceneObjects.destinations.forEach(dest => { dest.rotation.y -= 0.005; }); } // ==================================================================== // EVENT LISTENERS // ==================================================================== setupEventListeners() { // Window resize window.addEventListener('resize', () => this.onWindowResize()); // Mouse parallax (desktop only) if (this.isDesktop && CONFIG.performance.enableParallax && !this.prefersReducedMotion) { document.addEventListener('mousemove', (e) => this.onMouseMove(e)); } // Keyboard navigation document.addEventListener('keydown', (e) => this.onKeyDown(e)); } onWindowResize() { this.detectDeviceType(); if (this.camera && this.renderer) { this.camera.aspect = window.innerWidth / window.innerHeight; this.camera.updateProjectionMatrix(); this.renderer.setSize(window.innerWidth, window.innerHeight); } // Update viewport indicator if (CONFIG.devMode) { const viewportEl = document.getElementById('viewport'); if (viewportEl) { viewportEl.textContent = `${window.innerWidth}x${window.innerHeight}`; } } } onMouseMove(event) { // Normalize mouse coordinates to -1 to 1 this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1; this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; } onKeyDown(event) { // Allow escape to skip animation (accessibility) if (event.key === 'Escape') { this.skipAnimation(); } } skipAnimation() { if (window.ScrollTrigger) { window.scrollTo(0, CONFIG.timing.totalScrollHeight); } } // ==================================================================== // VIDEO LIGHTBOX // ==================================================================== openVideoLightbox() { const lightbox = document.createElement('div'); lightbox.id = 'mr-video-lightbox'; lightbox.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.9); z-index: 9999; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(10px); animation: fadeIn 0.3s ease; `; const videoContainer = document.createElement('div'); videoContainer.style.cssText = ` position: relative; width: 90%; max-width: 1200px; aspect-ratio: 16/9; background: #000; border-radius: 8px; overflow: hidden; `; const iframe = document.createElement('iframe'); iframe.src = `https://www.youtube.com/embed/${CONFIG.text.videoButton.youtubeId}?autoplay=1`; iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'; iframe.allowFullscreen = true; iframe.style.cssText = ` width: 100%; height: 100%; border: none; `; const closeBtn = document.createElement('button'); closeBtn.innerHTML = '×'; closeBtn.style.cssText = ` position: absolute; top: -50px; right: 0; font-size: 48px; color: white; background: transparent; border: none; cursor: pointer; padding: 10px; line-height: 1; transition: transform 0.2s; `; closeBtn.addEventListener('click', () => { document.body.removeChild(lightbox); }); closeBtn.addEventListener('mouseenter', () => { closeBtn.style.transform = 'scale(1.2)'; }); closeBtn.addEventListener('mouseleave', () => { closeBtn.style.transform = 'scale(1)'; }); videoContainer.appendChild(iframe); videoContainer.appendChild(closeBtn); lightbox.appendChild(videoContainer); // Close on background click lightbox.addEventListener('click', (e) => { if (e.target === lightbox) { document.body.removeChild(lightbox); } }); // Close on Escape key const escapeHandler = (e) => { if (e.key === 'Escape') { document.body.removeChild(lightbox); document.removeEventListener('keydown', escapeHandler); } }; document.addEventListener('keydown', escapeHandler); document.body.appendChild(lightbox); // Add animation const style = document.createElement('style'); style.textContent = ` @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } `; document.head.appendChild(style); } // ==================================================================== // ANIMATION LOOP // ==================================================================== animate() { requestAnimationFrame(() => this.animate()); // FPS counter this.frameCount++; const now = performance.now(); if (now >= this.lastFPSUpdate + 1000) { this.fps = Math.round(this.frameCount * 1000 / (now - this.lastFPSUpdate)); this.frameCount = 0; this.lastFPSUpdate = now; if (CONFIG.devMode) { const fpsEl = document.getElementById('fps'); if (fpsEl) fpsEl.textContent = this.fps; } } // Update 3D scene if (this.renderer && this.scene && this.camera) { // Apply subtle parallax to camera if (CONFIG.performance.enableParallax && !this.prefersReducedMotion) { this.camera.position.x += (this.mouse.x * 0.5 - this.camera.position.x) * 0.05; this.camera.position.y += (this.mouse.y * 0.5 - this.camera.position.y) * 0.05; this.camera.lookAt(this.scene.position); } // Rotate particle system slowly if (this.sceneObjects.particles) { this.sceneObjects.particles.rotation.y += 0.0005; this.sceneObjects.particles.rotation.x += 0.0002; } this.renderer.render(this.scene, this.camera); } } // ==================================================================== // UTILITIES // ==================================================================== log(...args) { if (CONFIG.devMode) { console.log('[MetaRouter Hero]', ...args); } } } // ======================================================================== // AUTO-INITIALIZE // ======================================================================== // Wait for DOM to be ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { new MetaRouterHero('metarouter-hero'); }); } else { new MetaRouterHero('metarouter-hero'); } })();

CLIENTS

The Home Depot and MetaRouter
Apple Leisure Group and MetaRouter

PARTNERS

Salesforce Registered ISV Partner

CLIENTS

The Home Depot and MetaRouter
Apple Leisure Group and MetaRouter

PARTNERS

Salesforce Registered ISV Partner

CLIENTS

The Home Depot and MetaRouter
Apple Leisure Group and MetaRouter

PARTNERS

Salesforce Registered ISV Partner
Enterprise-Grade Data You Can Trust

Real-Time Customer Data Management That’s Both Precise and Compliant

Retail & Commerce Media Networks

Unlock Anonymous to Known Measurement and Provide Rich Brand-Level Insights

Get the full picture of anonymous to known onsite ad performance and unlock rich, brand-specific insights to improve CPMs and grow the value of your media network.

Data Governance

Turn Your Private Data Infrastructure Into a Strategic Advantage

Capturing user preferences isn’t enough. MetaRouter ensures identity data is protected, privacy rules are enforced, and only AI-ready, compliant data flows across your tech stack for smarter personalization and decision-making.

Tag Management

Unlock Deeper Measurement and Attribution

1st party data collection and integration without 3rd-party tags. Speed up your website, improve user experience, and develop a rock-solid foundation for compliant data collection.

1
Collect

Accurate, Real-Time, and Secure Data Collection

+20%
In RoAS, CPA and Web Conversion Rate
127%
Desktop Lighthouse score uplift (SEO)
40%
INCREASE IN DATA COLLECTED

Build the foundation of your data strategy with real-time identity capture and AI-ready insights across every customer interaction.

  • Eliminate reliance on 3rd-party tags and gain faster page loads, higher data accuracy, and zero data leakage
  • Gather deep insights about anonymous to known customer journeys across your domains
  • Collect up to 40% more data with a true first-party collection architecture
2
Comply

Proactive Privacy and Consent Management

99.9%
uptime for privacy controls
40%→1%
variability in consent enforcement
100%
regional data sovereignty

Ensure compliance at the moment of collection, protecting both your organization and your customers.

  • Bring your own compliance framework, and stay ahead of privacy laws like GDPR, CCPA, and ADPPA while reducing risks of costly fines.
  • Achieve data sovereignty and airtight compliance with regional deployments and single-tenant data collection.
  • Seamlessly integrate consent management platforms and align data practices with user preferences through real-time consent enforcement.
3
Enrich

Unify Customer Identity and Activate AI-Ready Data to Power Business Growth

200%
increase in match rates
30%
more complete customer profiles
2x
Pipeline Growth without added spend

Enhance the value of your first-party data with advanced, anonymous-to-known identity enrichment, powering AI-driven experiences and boosting activation performance across your customer journeys.

  • Maximize anonymous match through the power of MetaRouter’s Sync Injector and stitch identities across domains and sessions without relying on PII.
  • Unlock overlooked data, including anonymous behavioral events.
  • Enable secure, server-side enrichment of known identifiers into your customers’ journeys in real time, cutting down on expensive ID resolution patterns and ensuring a unified, 360° customer view.
4
Integrate

Consistent, Real-Time Data Flow Across the All Tools

80+
server-side integrations
2.5-3
week implementation time
99.9%+
event processing reliability

Power Real-Time AI and Identity Workflows with Clean, Enriched Data, Streamlined Across Every Tool for Reliable, Scalable Integration.

  • Ensure real-time, server-side data integration into any platform or tool with no site updates or retagging, reducing engineering overhead.
  • Experience full adaptability with flexible data pipelines and in-flight transformations that are schema and spec agnostic.
  • Deliver high-quality data by defining, debugging, and enforcing schema standards to send clean, consistent data flows across your entire ecosystem.
5
Amplify

Increase ROI with AI-Ready, Identity-Resolved, Activation-Grade Customer Data

9.7%
increase in Return on Ad Spend
2.47%
revenue increase from performance gains
35%
lift in customer retention

Power AI-driven insights, targeted campaigns, and downstream engagement tools with accurate, activation-ready data.

  • Deliver consistent, insightful, and identity enriched data to your advertising platforms or Retail Media Networks to drive smarter segmentation, improved audience reach, and higher ROI.
  • Capture and deliver the right anonymous to know data to power end-to-end ad attribution for accurate omnichannel measurement.
  • Provide rich, brand-specific measurement and audience insights to the brands who participate in your retail media network.
Why MetaRouteR

Why Businesses Trust MetaRouter as Their Data Foundation

Compliance-First

Purpose-build for evolving global privacy regulations with proactive consent enforcement and complete data governance.

Retain full control over where and how your data is processed.

Data Sovereignty

Enterprise-Grade Flexibility

Customize every aspect of your data pipelines to suit your business needs.

Speed and Scale

Real-time data streaming built to handle enterprise-level complexity without sacrificing performance.

Extensive Integration Library

From pre-built to custom, connect your data your way: Paid Media, MarTech, Walled Gardens, Retargeting and more.

Customer Success in Action

See How We Help Organizations Transform their Data Strategies

+30%

more events in ALL channels (Meta/FB, Tik-Tok, Google, DSP)

15%

faster page load time = better SEO

+40%

increase in Return On Investment (ROI)

MetaRouter and The Home Depot

Isharpal Singh

Web Data Enablement & Analytics Manager

"In an era where client-side tracking faces limitations due to third-party cookie deprecation, MetaRouter emerges as a robust and scalable server-side alternative, empowering organizations with enhanced privacy, complete data governance, and the agility to navigate the digital analytics landscape confidently."
900ms

latency reduction in page load speed

2.47%

revenue increase

$247MM

annual revenue improvement

MetaRouter and Outside Media

Ross Durbin

Senior Product Manager

"With many product experiences, governance over the data pipelines and data destinations can become very difficult. MetaRouter helps with this by creating a centralized location for management and an easy to implement technology to create consistency across products.
MetaRouter has also helped us improve user identity resolution, maintain compliance with data privacy regulations, and improve the quality of the data being delivered to key tools downstream."

Nolan Garrido

VP of Engineering, Data, and AI

"MetaRouter has been a game-changer for CaliberMind. It has helped us efficiently manage our website data pipelines, ensuring high-quality data reliably flows seamlessly through our ecosystem. The BigQuery integration has proven invaluable, empowering us to leverage our data for actionable insights.Thanks to MetaRouter, we can focus on driving results rather than dealing with website data pipeline complexities."
2x+

Pipeline without increasing marketing spend

12%

Increase in ad-spend efficacy

+40%

Increase in "purchase event” data

MetaRouter and Begin Learning

Ripal Sanghani

(former) Senior Product Manager

"Once we discovered MetaRouter, it was a no-brainer. We can continue tracking the events we need to improve our product experience and understand our users—and confidently meet every regulation to ensure the utmost privacy for the many families who use our apps."
"MetaRouter ensures HIPAA compliance seamlessly, placing governance in our hands. With secure data processing and transport, and customizable encryption options, our PHI stays safe without the need for a BAA.
Thanks to MetaRouter, our sensitive data remains in our control, fitting neatly into our existing system and vendor preferences."

Alex Jacobson

Managing Director of Global Client Services

"In an era where client-side tracking faces limitations due to third-party cookie deprecation, MetaRouter emerges as a robust and scalable server-side alternative, empowering organizations with enhanced privacy, complete data governance, and the agility to navigate the digital analytics landscape confidently."

MetaRouter is rated 4.7 stars on G2 reviews.

MetaRouter G2 BadgesMetaRouter G2 On-Premise Data Integration Badge

Take Control and Unlock the Power of Identity-Driven Data

Your Data, Your Rules. Book a demo to see how.