Performance and Core Web Vitals
This guide explains how biskoui impacts Core Web Vitals, provides optimization strategies, and demonstrates how to maintain excellent performance while ensuring compliance.
Core Web Vitals Impact Analysis
biskoui Performance Profile
Resource Size:
- Main script: ~12KB gzipped
- CSS styles: ~3KB gzipped
- Total initial load: ~15KB
- Runtime memory: under 100KB
Loading Characteristics:
- First banner paint: under 100ms after script load
- Consent decision processing: under 10ms
- Cross-domain sync: under 50ms
Largest Contentful Paint (LCP)
biskoui is designed to minimize LCP impact:
✅ LCP-Friendly Patterns:
<!-- Preload critical resources -->
<head>
<link rel="preload" href="https://cdn.biskoui.com/biskoui.js" as="script">
<link rel="preconnect" href="https://api.biskoui.com">
<!-- High priority loading -->
<script src="https://cdn.biskoui.com/biskoui.js"
fetchpriority="high"></script>
</head>
🎯 Optimization Strategy:
// Defer non-critical consent UI
biskoui.configure({
display: {
mode: 'lazy', // Only show when needed
defer: 100, // Delay banner 100ms
respectLCP: true // Don't interfere with LCP
}
});
📊 LCP Impact Measurement:
// Monitor LCP with biskoui
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('LCP:', entry.startTime);
// Track if banner affected LCP
biskoui.performance.getLCPImpact().then(impact => {
console.log('biskoui LCP impact:', impact);
});
}
}).observe({entryTypes: ['largest-contentful-paint']});
First Input Delay (FID) / Interaction to Next Paint (INP)
biskoui maintains excellent interaction responsiveness:
⚡ Non-Blocking Initialization:
// Async initialization pattern
(function() {
const script = document.createElement('script');
script.async = true;
script.src = 'https://cdn.biskoui.com/biskoui.js';
script.onload = function() {
// Initialize without blocking main thread
biskoui.init({
async: true,
yieldToMain: true // Yield control between operations
});
};
document.head.appendChild(script);
})();
🎯 FID/INP Optimization:
// Debounce consent interactions
biskoui.configure({
interactions: {
debounce: 50, // Debounce clicks
passive: true, // Use passive event listeners
optimize: 'responsiveness'
}
});
// Monitor interaction performance
biskoui.performance.onInteraction((timing) => {
if (timing.delay > 100) {
console.warn('Slow consent interaction:', timing);
}
});
Cumulative Layout Shift (CLS)
Prevent layout shifts from consent banners:
🎯 Zero-CLS Banner Implementation:
/* Reserve space for banner */
.biskoui-banner-container {
/* Fixed positioning prevents layout shift */
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 9999;
/* Smooth appearance */
transform: translateY(100%);
transition: transform 0.3s ease-out;
}
.biskoui-banner-container.visible {
transform: translateY(0);
}
/* Alternative: Reserve banner space */
body.consent-pending {
padding-bottom: 80px; /* Reserve banner height */
}
JavaScript CLS Prevention:
// Pre-calculate banner dimensions
biskoui.configure({
layout: {
preventCLS: true,
reserveSpace: true,
smoothTransitions: true
}
});
// Monitor CLS impact
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (entry.hadRecentInput) continue;
console.log('CLS:', entry.value);
// Check if biskoui caused shift
if (entry.sources.some(source =>
source.node?.classList?.contains('biskoui-banner'))) {
console.warn('biskoui caused layout shift');
}
}
}).observe({entryTypes: ['layout-shift']});
Performance Optimization Strategies
1. Resource Loading Optimization
Critical Resource Path:
<!DOCTYPE html>
<html>
<head>
<!-- Step 1: DNS prefetch -->
<link rel="dns-prefetch" href="//cdn.biskoui.com">
<link rel="dns-prefetch" href="//api.biskoui.com">
<!-- Step 2: Preconnect for faster handshake -->
<link rel="preconnect" href="https://cdn.biskoui.com" crossorigin>
<!-- Step 3: Preload critical script -->
<link rel="preload" href="https://cdn.biskoui.com/biskoui.js"
as="script" crossorigin>
<!-- Step 4: Load with priority -->
<script src="https://cdn.biskoui.com/biskoui.js"
fetchpriority="high" crossorigin></script>
</head>
Advanced Caching Strategy:
// Configure aggressive caching
biskoui.configure({
cache: {
strategy: 'stale-while-revalidate',
maxAge: 86400, // 24 hours
preload: true, // Preload next visit
compression: 'br' // Brotli compression
}
});
2. Lazy Loading & Deferred Consent
Smart Loading Pattern:
// Only load banner when user scrolls or after delay
const loadBanner = () => {
if (document.readyState === 'complete') {
biskoui.showBanner();
} else {
window.addEventListener('load', () => {
setTimeout(() => biskoui.showBanner(), 500);
});
}
};
// Trigger on user interaction
let userInteracted = false;
['scroll', 'mousedown', 'touchstart', 'keydown'].forEach(event => {
document.addEventListener(event, () => {
if (!userInteracted) {
userInteracted = true;
loadBanner();
}
}, { once: true, passive: true });
});
Intersection Observer Pattern:
// Show banner when user reaches footer
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
biskoui.showBanner();
observer.disconnect();
}
});
});
// Observe footer element
const footer = document.querySelector('footer');
if (footer) observer.observe(footer);
3. Script Tag Management
Optimized Tag Loading:
<!-- Group scripts by consent category -->
<script type="text/plain" data-biskoui-category="analytics">
// Analytics code - loads when analytics consent given
(function(i,s,o,g,r,a,m){...})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
</script>
<script type="text/plain" data-biskoui-category="marketing">
// Marketing code - loads when marketing consent given
!function(f,b,e,v,n,t,s){...}(window,document,'script','https://connect.facebook.net/en_US/fbevents.js');
</script>
Dynamic Loading with Performance Budget:
const performanceBudget = {
analytics: 50, // Max 50KB for analytics scripts
marketing: 100, // Max 100KB for marketing scripts
functional: 30 // Max 30KB for functional scripts
};
biskoui.consent.onChange((consent) => {
Object.keys(consent).forEach(category => {
if (consent[category]) {
loadCategoryScripts(category, performanceBudget[category]);
}
});
});
function loadCategoryScripts(category, budget) {
const scripts = document.querySelectorAll(
`script[data-biskoui-category="${category}"]`
);
let loadedSize = 0;
scripts.forEach(script => {
const size = script.textContent.length;
if (loadedSize + size <= budget * 1024) {
script.type = 'text/javascript';
loadedSize += size;
} else {
console.warn(`Performance budget exceeded for ${category}`);
}
});
}
Framework-Specific Optimizations
React Performance Patterns
Optimized React Hook:
import { useState, useEffect, useCallback, useRef } from 'react';
export function useConsentOptimized() {
const [consent, setConsent] = useState(null);
const [loading, setLoading] = useState(true);
const unsubscribeRef = useRef();
// Memoized consent handler
const handleConsentChange = useCallback((newConsent) => {
setConsent(newConsent);
setLoading(false);
}, []);
useEffect(() => {
// Check if consent already loaded
const existingConsent = biskoui.consent.getCurrent();
if (existingConsent) {
handleConsentChange(existingConsent);
return;
}
// Subscribe to changes
unsubscribeRef.current = biskoui.consent.onChange(handleConsentChange);
return () => {
unsubscribeRef.current?.();
};
}, [handleConsentChange]);
return { consent, loading };
}
// Usage with React.memo for performance
const AnalyticsComponent = React.memo(() => {
const { consent, loading } = useConsentOptimized();
if (loading || !consent?.analytics) return null;
return <AnalyticsWidget />;
});
Next.js Optimization
Optimized Next.js Integration:
// pages/_app.tsx
import { useEffect } from 'react';
import type { AppProps } from 'next/app';
function MyApp({ Component, pageProps }: AppProps) {
useEffect(() => {
// Optimize for Next.js routing
const handleRouteStart = () => {
// Pause tracking during navigation
biskoui.performance.pauseTracking();
};
const handleRouteComplete = () => {
// Resume tracking after navigation
biskoui.performance.resumeTracking();
// Check consent for new page
biskoui.consent.checkPageConsent();
};
Router.events.on('routeChangeStart', handleRouteStart);
Router.events.on('routeChangeComplete', handleRouteComplete);
return () => {
Router.events.off('routeChangeStart', handleRouteStart);
Router.events.off('routeChangeComplete', handleRouteComplete);
};
}, []);
return <Component {...pageProps} />;
}
Vue.js Performance
Optimized Vue Composition API:
// composables/useConsent.ts
import { ref, onMounted, onUnmounted, computed } from 'vue';
export function useConsent() {
const consent = ref(null);
const loading = ref(true);
let unsubscribe = null;
// Computed properties for specific consents
const canTrackAnalytics = computed(() => consent.value?.analytics ?? false);
const canShowMarketing = computed(() => consent.value?.marketing ?? false);
onMounted(async () => {
// Check existing consent first
const existing = await biskoui.consent.getCurrent();
if (existing) {
consent.value = existing;
loading.value = false;
return;
}
// Subscribe to changes
unsubscribe = biskoui.consent.onChange((newConsent) => {
consent.value = newConsent;
loading.value = false;
});
});
onUnmounted(() => {
unsubscribe?.();
});
return {
consent: readonly(consent),
loading: readonly(loading),
canTrackAnalytics,
canShowMarketing
};
}
Performance Monitoring & Analytics
Core Web Vitals Tracking
Comprehensive Performance Monitoring:
// Track all Core Web Vitals with biskoui context
function initPerformanceMonitoring() {
// LCP tracking
new PerformanceObserver((entryList) => {
const lcp = entryList.getEntries()[0];
biskoui.analytics.track('core_web_vital', {
metric: 'LCP',
value: lcp.startTime,
element: lcp.element?.tagName,
consentBannerVisible: biskoui.ui.isVisible()
});
}).observe({entryTypes: ['largest-contentful-paint']});
// FID tracking
new PerformanceObserver((entryList) => {
const fid = entryList.getEntries()[0];
biskoui.analytics.track('core_web_vital', {
metric: 'FID',
value: fid.processingStart - fid.startTime,
consentDelay: biskoui.performance.getConsentDelay()
});
}).observe({entryTypes: ['first-input']});
// CLS tracking
let clsValue = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
// Report CLS periodically
setTimeout(() => {
biskoui.analytics.track('core_web_vital', {
metric: 'CLS',
value: clsValue,
bannerCLSImpact: biskoui.performance.getCLSImpact()
});
}, 5000);
}).observe({entryTypes: ['layout-shift']});
}
// Initialize after biskoui loads
biskoui.ready(initPerformanceMonitoring);
Performance Budget Monitoring
Script Loading Performance:
// Monitor script loading performance
const performanceMonitor = {
budgets: {
analytics: { size: 50000, timing: 1000 },
marketing: { size: 100000, timing: 2000 },
functional: { size: 30000, timing: 500 }
},
trackScriptLoad(category, startTime, size) {
const loadTime = performance.now() - startTime;
const budget = this.budgets[category];
const metrics = {
category,
loadTime,
size,
budgetExceeded: {
timing: loadTime > budget.timing,
size: size > budget.size
}
};
biskoui.analytics.track('script_performance', metrics);
if (metrics.budgetExceeded.timing || metrics.budgetExceeded.size) {
console.warn(`Performance budget exceeded for ${category}:`, metrics);
}
}
};
// Use with dynamic script loading
biskoui.consent.onChange((consent) => {
Object.keys(consent).forEach(category => {
if (consent[category]) {
const startTime = performance.now();
loadCategoryScripts(category).then(scripts => {
const totalSize = scripts.reduce((sum, script) => sum + script.size, 0);
performanceMonitor.trackScriptLoad(category, startTime, totalSize);
});
}
});
});
Advanced Performance Techniques
1. Critical Path Optimization
Above-the-fold Consent Pattern:
<!-- Inline critical consent styles -->
<style>
.biskoui-banner-critical {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: #000;
color: #fff;
padding: 1rem;
font-family: system-ui;
z-index: 9999;
transform: translateY(100%);
}
.biskoui-banner-critical.visible {
transform: translateY(0);
}
</style>
<!-- Minimal inline script for immediate display -->
<script>
(function() {
// Check if consent already given
const consent = localStorage.getItem('biskoui-consent');
if (!consent) {
// Show minimal banner immediately
document.body.insertAdjacentHTML('beforeend',
'<div class="biskoui-banner-critical visible">' +
'We use cookies. <button onclick="acceptAll()">Accept</button>' +
'</div>'
);
}
window.acceptAll = function() {
localStorage.setItem('biskoui-consent', '{"analytics":true,"marketing":true}');
document.querySelector('.biskoui-banner-critical').remove();
};
})();
</script>
2. Service Worker Caching
Advanced Caching Strategy:
// sw.js - Service Worker for biskoui caching
const CACHE_NAME = 'biskoui-v1';
const RESOURCES = [
'https://cdn.biskoui.com/biskoui.js',
'https://cdn.biskoui.com/biskoui.css'
];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(RESOURCES))
);
});
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('biskoui.com')) {
event.respondWith(
caches.match(event.request)
.then(response => {
if (response) {
// Return cached version
fetch(event.request).then(fetchResponse => {
// Update cache in background
caches.open(CACHE_NAME)
.then(cache => cache.put(event.request, fetchResponse.clone()));
});
return response;
}
return fetch(event.request);
})
);
}
});
3. Edge Computing Integration
Cloudflare Workers Example:
// Cloudflare Worker for consent pre-processing
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
// Check for existing consent in cookie
const consent = getCookieValue(request.headers.get('Cookie'), 'biskoui-consent');
if (consent) {
// User has consent - inject optimized scripts
const response = await fetch(request);
const html = await response.text();
const optimizedHtml = html.replace(
'<head>',
'<head><script>window.BISKOUI_CONSENT=' + consent + ';</script>'
);
return new Response(optimizedHtml, {
headers: response.headers
});
}
return fetch(request);
}
Performance Testing & Validation
Automated Performance Testing
Lighthouse CI Integration:
// lighthouse.config.js
module.exports = {
ci: {
collect: {
url: ['http://localhost:3000'],
settings: {
chromeFlags: '--no-sandbox',
preset: 'desktop'
}
},
assert: {
assertions: {
'categories:performance': ['warn', { minScore: 0.9 }],
'categories:accessibility': ['error', { minScore: 0.9 }],
'largest-contentful-paint': ['warn', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }]
}
}
}
};
WebPageTest Integration:
// Test biskoui performance impact
const WebPageTest = require('webpagetest');
const wpt = new WebPageTest('www.webpagetest.org', 'YOUR_API_KEY');
async function testConsentPerformance() {
// Test without consent banner
const baselineTest = await wpt.runTest('https://your-site.com?no-banner=1');
// Test with consent banner
const consentTest = await wpt.runTest('https://your-site.com');
// Compare results
const comparison = {
lcpDiff: consentTest.data.median.firstView.largestContentfulPaint -
baselineTest.data.median.firstView.largestContentfulPaint,
fidDiff: consentTest.data.median.firstView.firstInputDelay -
baselineTest.data.median.firstView.firstInputDelay,
clsDiff: consentTest.data.median.firstView.cumulativeLayoutShift -
baselineTest.data.median.firstView.cumulativeLayoutShift
};
console.log('biskoui Performance Impact:', comparison);
}
Best Practices Summary
✅ Performance Checklist
-
Resource Loading
- Use
preloadfor biskoui script - Enable Brotli/Gzip compression
- Implement proper caching headers
- Use CDN with global edge locations
- Use
-
Core Web Vitals
- LCP impact < 100ms
- FID/INP impact < 50ms
- CLS impact = 0 (fixed positioning)
- Monitor with RUM tools
-
Script Management
- Block third-party scripts until consent
- Implement performance budgets
- Use lazy loading for non-critical consent
- Cleanup event listeners in SPAs
-
Framework Integration
- Use optimized hooks/composables
- Implement proper memoization
- Handle route changes efficiently
- Prevent memory leaks
-
Monitoring & Testing
- Set up Core Web Vitals tracking
- Monitor consent banner impact
- Test with slow networks
- Validate on mobile devices
Following these practices ensures biskoui enhances your compliance posture without compromising user experience or search engine rankings.