/** * A/B Testing for Featured Schools Widgets * Tests Mastodon carousel (Variant A) vs Morpheus/Archer listings (Variant B) */ (function() { 'use strict'; // Configuration var COOKIE_NAME = 'widget_ab_test_variant'; var COOKIE_DURATION = 30; // days var VARIANTS = ['mastodon', 'morpheus']; var TRAFFIC_SPLIT = 0.5; // 50/50 split var GA_CATEGORY = 'Featured Schools Widget AB Test'; /** * Get cookie value by name */ function getCookie(name) { var nameEQ = name + '='; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) === ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); } return null; } /** * Set cookie with expiration */ function setCookie(name, value, days) { var expires = ''; if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = '; expires=' + date.toUTCString(); } document.cookie = name + '=' + (value || '') + expires + '; path=/'; } /** * Randomly assign user to a variant */ function assignVariant() { var random = Math.random(); var variant = random < TRAFFIC_SPLIT ? VARIANTS[0] : VARIANTS[1]; setCookie(COOKIE_NAME, variant, COOKIE_DURATION); trackEvent('variant_assigned', variant); return variant; } /** * Get or assign variant to user */ function getVariant() { var variant = getCookie(COOKIE_NAME); if (!variant || VARIANTS.indexOf(variant) === -1) { variant = assignVariant(); } return variant; } /** * Show the appropriate widget variant */ function showVariant(variant) { var variantAElement = document.getElementById('widget-variant-a'); var variantBElement = document.getElementById('widget-variant-b'); if (!variantAElement || !variantBElement) { console.error('Widget A/B test: Widget elements not found'); return; } if (variant === 'mastodon') { variantAElement.style.display = 'block'; variantBElement.style.display = 'none'; } else { variantAElement.style.display = 'none'; variantBElement.style.display = 'block'; } trackEvent('widget_viewed', variant); } /** * Track event to Google Analytics */ function trackEvent(action, label) { // Check if cfTracker is available (College Factual custom tracker) if (typeof window.cfTracker !== 'undefined' && window.cfTracker.trackEvent) { window.cfTracker.trackEvent(GA_CATEGORY, action, label); console.log('A/B Test Event (cfTracker):', action, label); } // Use dataLayer for GTM/GA4 if available else if (typeof window.dataLayer !== 'undefined' && Array.isArray(window.dataLayer)) { var eventData = { 'event': 'ab_test_event', 'event_category': GA_CATEGORY, 'event_action': action, 'event_label': label, 'ab_test_variant': label }; window.dataLayer.push(eventData); console.log('A/B Test Event (dataLayer):', eventData); } // Use gtag if available (direct GA4) else if (typeof gtag !== 'undefined') { gtag('event', action, { 'event_category': GA_CATEGORY, 'event_label': label, 'ab_test_variant': label }); console.log('A/B Test Event (gtag):', action, label); } // Fallback to Universal Analytics else if (typeof ga !== 'undefined') { ga('send', 'event', GA_CATEGORY, action, label); console.log('A/B Test Event (UA):', action, label); } // Log if no tracking available else { console.log('A/B Test Event (no tracker):', GA_CATEGORY, action, label); } } /** * Setup click tracking for widget interactions */ function setupTracking(variant) { var widgetElement = variant === 'mastodon' ? document.getElementById('widget-variant-a') : document.getElementById('widget-variant-b'); if (!widgetElement) { return; } // Track clicks on links within the widget (for Mastodon carousel) if (variant === 'mastodon') { var links = widgetElement.querySelectorAll('a'); for (var i = 0; i < links.length; i++) { links[i].addEventListener('click', function() { trackEvent('widget_clicked', variant); }); } // Track form submissions (for Mastodon widget) var forms = widgetElement.querySelectorAll('form'); for (var j = 0; j < forms.length; j++) { forms[j].addEventListener('submit', function() { trackEvent('form_submitted', variant); }); } } // Track Morpheus/Archer widget events (for Morpheus listings) else if (variant === 'morpheus') { setupArcherEventTracking(variant); } } /** * Setup Morpheus/Archer widget event tracking * Listens for custom events emitted by the Archer widget */ function setupArcherEventTracking(variant) { // Track when Morpheus results are loaded document.addEventListener('archer:results_loaded', function(e) { trackEvent('widget_results_loaded', variant); console.log('Morpheus widget: Results loaded', e.detail); }); // Track when individual ads are loaded document.addEventListener('archer:ad_loaded', function(e) { // Note: This fires once per ad, so we don't track every instance // to avoid spamming analytics console.log('Morpheus widget: Ad loaded', e.detail); }); // Track when users click on ads (THIS IS THE KEY EVENT) document.addEventListener('archer:ad_clicked', function(e) { trackEvent('widget_clicked', variant); console.log('Morpheus widget: Ad clicked', e.detail); }); // Track when users click "View More Programs" document.addEventListener('archer:view_more_clicked', function(e) { trackEvent('widget_view_more_clicked', variant); console.log('Morpheus widget: View More clicked', e.detail); }); console.log('Morpheus widget: Event listeners attached for variant', variant); } /** * Initialize A/B test */ function init() { try { // Get or assign variant var variant = getVariant(); console.log('Widget A/B Test: Assigned variant =', variant); // Show appropriate widget showVariant(variant); // Setup interaction tracking setupTracking(variant); } catch (error) { console.error('Widget A/B test initialization error:', error); // Fallback to showing variant B (current production widget) var variantBElement = document.getElementById('widget-variant-b'); if (variantBElement) { variantBElement.style.display = 'block'; } } } // Expose init function globally window.WidgetABTest = { init: init, getVariant: getVariant, trackEvent: trackEvent }; })();