Skip to main content

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
}
});

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

  1. Resource Loading

    • Use preload for biskoui script
    • Enable Brotli/Gzip compression
    • Implement proper caching headers
    • Use CDN with global edge locations
  2. Core Web Vitals

    • LCP impact < 100ms
    • FID/INP impact < 50ms
    • CLS impact = 0 (fixed positioning)
    • Monitor with RUM tools
  3. Script Management

    • Block third-party scripts until consent
    • Implement performance budgets
    • Use lazy loading for non-critical consent
    • Cleanup event listeners in SPAs
  4. Framework Integration

    • Use optimized hooks/composables
    • Implement proper memoization
    • Handle route changes efficiently
    • Prevent memory leaks
  5. 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.