1/* Klaviyo Back in Stock â frontend handler (Client Events API) */ 2(function () { 3 'use strict'; 4 5 function isEmail(v) { 6 return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v); 7 } 8 9 function setMessage(el, text, type) { 10 if (!el) return; 11 el.textContent = text || ''; 12 el.classList.remove('is-success', 'is-error'); 13 if (type) el.classList.add('is-' + type); 14 } 15 16 /* ===== Form submission ===== */ 17 18 function bindForm(form) { 19 form.addEventListener('submit', async function (e) { 20 e.preventDefault(); 21 22 var msg = form.querySelector('.klaviyo-bis-message'); 23 var btn = form.querySelector('.klaviyo-bis-button'); 24 var emailEl = form.querySelector('input[name="email"]'); 25 var defaultEl = form.querySelector('.klaviyo-bis-default'); 26 var successEl = form.querySelector('.klaviyo-bis-success'); 27 28 setMessage(msg, '', null); 29 30 var email = (emailEl.value || '').trim(); 31 if (!isEmail(email)) { 32 setMessage(msg, KlaviyoBISConfig.messages.invalid_email, 'error'); 33 emailEl.focus(); 34 return; 35 } 36 37 var companyId = KlaviyoBISConfig.company_id; 38 if (!companyId) { 39 setMessage(msg, 'Klaviyo Company ID not configured.', 'error'); 40 return; 41 } 42 43 var eventName = KlaviyoBISConfig.event_name || 'Subscribed to Back in Stock'; 44 var productId = form.dataset.productId || ''; 45 var productName = form.dataset.productName || ''; 46 47 var originalLabel = btn.textContent; 48 btn.disabled = true; 49 btn.textContent = KlaviyoBISConfig.messages.submitting; 50 51 var payload = { 52 data: { 53 type: 'event', 54 attributes: { 55 properties: { 56 ProductID: productId, 57 ProductName: productName, 58 ProductURL: window.location.href 59 }, 60 metric: { 61 data: { 62 type: 'metric', 63 attributes: { name: eventName } 64 } 65 }, 66 profile: { 67 data: { 68 type: 'profile', 69 attributes: { email: email } 70 } 71 } 72 } 73 } 74 }; 75 76 try { 77 var res = await fetch( 78 'https://a.klaviyo.com/client/events/?company_id=' + encodeURIComponent(companyId), 79 { 80 method: 'POST', 81 headers: { 82 'Content-Type': 'application/json', 83 'revision': KlaviyoBISConfig.api_revision || '2024-10-15' 84 }, 85 body: JSON.stringify(payload) 86 } 87 ); 88 89 // Klaviyo returns 202 Accepted on success 90 if (res.ok || res.status === 202) { 91 if (defaultEl) defaultEl.hidden = true; 92 if (successEl) successEl.hidden = false; 93 form.reset(); 94 } else { 95 setMessage(msg, KlaviyoBISConfig.messages.error, 'error'); 96 } 97 } catch (err) { 98 setMessage(msg, KlaviyoBISConfig.messages.error, 'error'); 99 } finally { 100 btn.disabled = false; 101 btn.textContent = originalLabel; 102 } 103 }); 104 } 105 106 /* ===== Modal ===== */ 107 108 function openModal() { 109 var modal = document.getElementById('klaviyo-bis-modal'); 110 if (!modal) return; 111 112 var defaultEl = modal.querySelector('.klaviyo-bis-default'); 113 var successEl = modal.querySelector('.klaviyo-bis-success'); 114 if (defaultEl && successEl) { 115 defaultEl.hidden = false; 116 successEl.hidden = true; 117 } 118 119 modal.hidden = false; 120 modal.setAttribute('aria-hidden', 'false'); 121 document.body.classList.add('klaviyo-bis-modal-open'); 122 setTimeout(function () { 123 var input = modal.querySelector('input[name="email"]'); 124 if (input) input.focus(); 125 }, 50); 126 } 127 128 function closeModal() { 129 var modal = document.getElementById('klaviyo-bis-modal'); 130 if (!modal) return; 131 modal.hidden = true; 132 modal.setAttribute('aria-hidden', 'true'); 133 document.body.classList.remove('klaviyo-bis-modal-open'); 134 } 135 136 function bindModalEvents() { 137 document.addEventListener('click', function (e) { 138 if (e.target.closest('[data-klaviyo-bis-open]')) { 139 e.preventDefault(); 140 openModal(); 141 } else if (e.target.closest('[data-klaviyo-bis-close]')) { 142 closeModal(); 143 } 144 }); 145 146 document.addEventListener('keydown', function (e) { 147 if (e.key === 'Escape') closeModal(); 148 }); 149 } 150 151 /* ===== Init ===== */ 152 153 function init() { 154 document.querySelectorAll('.klaviyo-bis-form').forEach(bindForm); 155 bindModalEvents(); 156 157 window.KlaviyoBIS = window.KlaviyoBIS || {};
158 window.KlaviyoBIS.openModal = openModal; 159 window.KlaviyoBIS.closeModal = closeModal; 160 } 161 162 if (document.readyState === 'loading') { 163 document.addEventListener('DOMContentLoaded', init); 164 } else { 165 init(); 166 } 167})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.