(function (){
'use strict';
var config=window.bpAnalyticsConfig||{};
var queueKey='bp_analytics_event_queue_v1';
var sentKey='bp_analytics_sent_ids_v1';
var attributionKey='bp_analytics_attribution_v1';
var itemKey='bp_analytics_last_item_v1';
var eventNames=['select_content', 'view_item', 'select_item', 'add_to_cart', 'view_cart', 'begin_checkout', 'add_payment_info', 'checkout_error'];
var parameterNames=['content_type', 'content_id', 'proxy_type', 'package_size', 'entry_surface', 'route_group', 'currency', 'value', 'funnel_version', 'event_id', 'payment_type', 'error_category', 'items'];
var entrySurfaces=['public_website', 'whois', 'chrome_extension', 'client_area', 'direct_store'];
var routeGroups=['public_site', 'whois', 'whmcs', 'whmcs_order'];
var proxyTypes=['dedicated', 'semi-dedicated'];
var paymentTypes=['paypal', 'card', 'other'];
var errorCategories=['terms', 'payment', 'account', 'validation', 'processing'];
var currencies=['USD', 'EUR', 'GBP', 'RON'];
function read(key, fallback){
try {
var parsed=JSON.parse(window.sessionStorage.getItem(key));
return parsed===null ? fallback:parsed;
} catch (error){
return fallback;
}}
function write(key, value){
try {
window.sessionStorage.setItem(key, JSON.stringify(value));
return true;
} catch (error){
return false;
}}
function identifier(prefix){
var random=window.crypto&&window.crypto.getRandomValues
? window.crypto.getRandomValues(new Uint32Array(2))
: [Date.now(), Math.floor(Math.random() * 1000000000)];
return prefix + '-' + Date.now().toString(36) + '-' + Number(random[0]).toString(36) + Number(random[1]).toString(36);
}
function routeGroup(pathname){
var path=String(pathname||'').toLowerCase();
if(path==='/whois'||path==='/whois/') return 'whois';
if(path.indexOf('/panel/cart.php')===0) return 'whmcs_order';
if(path.indexOf('/panel/')===0) return 'whmcs';
return 'public_site';
}
function campaignValue(value){
return String(value||'').toLowerCase().replace(/[^a-z0-9._+-]/g, '_').slice(0, 100);
}
function currentCampaign(){
var params=new URLSearchParams(window.location.search||'');
var source=campaignValue(params.get('utm_source'));
var medium=campaignValue(params.get('utm_medium'));
var campaign=campaignValue(params.get('utm_campaign'));
var referrerHost='';
var effectiveSource;
try {
referrerHost=document.referrer ? campaignValue(new URL(document.referrer).hostname):'';
} catch (error){
referrerHost='';
}
if(!source&&referrerHost&&referrerHost!==campaignValue(window.location.hostname)){
source=referrerHost;
medium='referral';
}
effectiveSource=source||'direct';
return {
source: effectiveSource,
medium: medium||(effectiveSource==='direct' ? 'none':'campaign'),
campaign: campaign
};}
function entrySurface(source){
var storeRoute=new URLSearchParams(window.location.search||'').get('rp')||'';
var referrerPath='';
var referrerHost='';
var referrerStoreRoute='';
try {
var referrerUrl=document.referrer ? new URL(document.referrer):null;
referrerPath=referrerUrl ? referrerUrl.pathname:'';
referrerHost=referrerUrl ? referrerUrl.hostname:'';
referrerStoreRoute=referrerUrl ? (referrerUrl.searchParams.get('rp')||''):'';
} catch (error){
referrerPath='';
referrerHost='';
referrerStoreRoute='';
}
if(source==='chrome_extension') return 'chrome_extension';
if(routeGroup(window.location.pathname)==='whois') return 'whois';
if(referrerHost===window.location.hostname&&referrerPath.indexOf('/panel/')===0&&referrerStoreRoute.indexOf('/store/')!==0) return 'client_area';
if(window.location.pathname.indexOf('/panel/')===0&&storeRoute.indexOf('/store/')===0) return 'direct_store';
if(window.location.pathname.indexOf('/panel/')===0) return 'client_area';
return 'public_website';
}
function initialAttribution(){
var existing=read(attributionKey, null);
var current=currentCampaign();
if(existing&&existing.createdAt&&Date.now() - existing.createdAt < 7776000000){
if(current.source!=='direct'){
existing.lastSource=current.source;
existing.lastMedium=current.medium;
existing.lastCampaign=current.campaign;
write(attributionKey, existing);
}
return existing;
}
existing={
firstSource: current.source,
firstMedium: current.medium,
firstCampaign: current.campaign,
lastSource: current.source,
lastMedium: current.medium,
lastCampaign: current.campaign,
landingRoute: routeGroup(window.location.pathname),
entrySurface: entrySurface(current.source),
createdAt: Date.now()
};
write(attributionKey, existing);
return existing;
}
function allowed(value, values){
return values.indexOf(value)!==-1 ? value:'';
}
function positiveNumber(value){
var number=Number(value);
return Number.isFinite(number)&&number > 0 ? Math.round(number * 100) / 100:null;
}
function packageSize(value){
var number=Number(value);
return Number.isInteger(number)&&number > 0&&number <=100000 ? number:null;
}
function sanitizeItem(item){
var id=String(item&&item.item_id||'');
var name=String(item&&item.item_name||'');
var category=allowed(String(item&&item.item_category||''), proxyTypes);
var variant=String(item&&item.item_variant||'');
var price=positiveNumber(item&&item.price);
if(!/^[A-Za-z0-9._-]{1,64}$/.test(id)||!/^\d{1,6} (?:Dedicated|Semi-dedicated) proxies$/.test(name)) return null;
if(!category||!/^\d{1,6} proxies$/.test(variant)||null===price) return null;
return {
item_id: id,
item_name: name,
item_category: category,
item_variant: variant,
price: price,
quantity: 1
};}
function sanitizeCommerceState(item){
var cleanItem=sanitizeItem(item);
var currency=allowed(String(item&&item.currency||'').toUpperCase(), currencies);
var size=packageSize(item&&item.package_size);
var type=allowed(String(item&&item.proxy_type||''), proxyTypes);
if(!cleanItem||!currency||null===size||!type) return null;
if(cleanItem.item_category!==type||cleanItem.item_variant!==size + ' proxies') return null;
cleanItem.currency=currency;
cleanItem.package_size=size;
cleanItem.proxy_type=type;
return cleanItem;
}
function sanitizeParams(params){
var clean={};
parameterNames.forEach(function (key){
if(!Object.prototype.hasOwnProperty.call(params||{}, key)) return;
if(key==='items'){
clean.items=Array.isArray(params.items) ? params.items.slice(0, 20).map(sanitizeItem).filter(Boolean):[];
return;
}
if(key==='content_type') clean[key]=params[key]==='cta' ? 'cta':'';
if(key==='content_id') clean[key]=/^whois-(?:proxy-test|reputation-check|whois-guide|dedicated-plans)$/.test(String(params[key])) ? String(params[key]):'';
if(key==='proxy_type') clean[key]=allowed(String(params[key]), proxyTypes);
if(key==='package_size') clean[key]=packageSize(params[key]);
if(key==='entry_surface') clean[key]=allowed(String(params[key]), entrySurfaces);
if(key==='route_group') clean[key]=allowed(String(params[key]), routeGroups);
if(key==='currency') clean[key]=allowed(String(params[key]).toUpperCase(), currencies);
if(key==='value') clean[key]=positiveNumber(params[key]);
if(key==='funnel_version') clean[key]=/^\d{4}-\d{2}-\d{2}\.\d+$/.test(String(params[key])) ? String(params[key]):'';
if(key==='event_id') clean[key]=/^[A-Za-z0-9:._-]{1,100}$/.test(String(params[key])) ? String(params[key]):'';
if(key==='payment_type') clean[key]=allowed(String(params[key]), paymentTypes);
if(key==='error_category') clean[key]=allowed(String(params[key]), errorCategories);
});
Object.keys(clean).forEach(function (key){
if(clean[key]===''||clean[key]===null||(Array.isArray(clean[key])&&!clean[key].length)) delete clean[key];
});
return clean;
}
function flush(){
var queue;
var sent;
var remaining=[];
if(!config.enabled||typeof window.gtag!=='function') return;
queue=read(queueKey, []);
sent=read(sentKey, []);
if(!Array.isArray(queue)) queue=[];
if(!Array.isArray(sent)) sent=[];
queue.forEach(function (entry){
if(!entry||!entry.params||sent.indexOf(entry.params.event_id)!==-1) return;
try {
window.gtag('event', entry.name, Object.assign({}, entry.params, { send_to: config.measurementId }));
sent.push(entry.params.event_id);
} catch (error){
remaining.push(entry);
}});
write(sentKey, sent.slice(-100));
write(queueKey, remaining.slice(-30));
}
function track(name, params, dedupeKey){
var queue;
var sent;
var eventId;
var attribution;
var clean;
if(eventNames.indexOf(name)===-1) return false;
queue=read(queueKey, []);
sent=read(sentKey, []);
if(!Array.isArray(queue)) queue=[];
if(!Array.isArray(sent)) sent=[];
eventId=dedupeKey||identifier(name);
if(!/^[A-Za-z0-9:._-]{1,100}$/.test(eventId)) return false;
if(sent.indexOf(eventId)!==-1||queue.some(function (entry){ return entry.params.event_id===eventId; })) return false;
attribution=initialAttribution();
clean=sanitizeParams(Object.assign({}, params||{}, {
event_id: eventId,
funnel_version: config.funnelVersion||'2026-07-19.1',
route_group: routeGroup(window.location.pathname),
entry_surface: attribution.entrySurface
}));
if(!clean.event_id||!clean.funnel_version||!clean.route_group||!clean.entry_surface) return false;
queue.push({ name: name, params: clean, queuedAt: Date.now() });
write(queueKey, queue.slice(-30));
flush();
return true;
}
function captureIds(callback){
var values={};
var settled=false;
if(typeof callback!=='function') return;
if(typeof window.gtag!=='function'||!config.measurementId){
callback(null);
return;
}
function finish(){
if(!settled&&values.clientId&&values.sessionId){
settled=true;
callback(values);
}}
try {
window.gtag('get', config.measurementId, 'client_id', function (value){
values.clientId=String(value||'');
finish();
});
window.gtag('get', config.measurementId, 'session_id', function (value){
values.sessionId=String(value||'');
finish();
});
} catch (error){
settled=true;
callback(null);
return;
}
window.setTimeout(function (){
if(!settled){
settled=true;
callback(null);
}}, 1200);
}
function bridgeInput(name){
return document.querySelector('input[type="hidden"][form="frmCheckout"][name="' + name + '"]');
}
function fillCheckoutAttribution(){
var token=bridgeInput('bp_analytics_token');
if(!token||!/^[a-f0-9]{64}$/.test(String(token.value||''))) return;
captureIds(function (ids){
var attribution;
var item;
var values;
if(!ids
|| !/^\d{1,20}\.\d{1,20}$/.test(String(ids.clientId||''))
|| !/^\d{1,20}$/.test(String(ids.sessionId||''))
) return;
attribution=initialAttribution();
item=sanitizeCommerceState(read(itemKey, null));
values={
bp_analytics_consent: 'granted',
bp_analytics_client_id: ids.clientId,
bp_analytics_session_id: ids.sessionId,
bp_analytics_first_source: campaignValue(attribution.firstSource),
bp_analytics_first_medium: campaignValue(attribution.firstMedium),
bp_analytics_first_campaign: campaignValue(attribution.firstCampaign),
bp_analytics_last_source: campaignValue(attribution.lastSource),
bp_analytics_last_medium: campaignValue(attribution.lastMedium),
bp_analytics_last_campaign: campaignValue(attribution.lastCampaign),
bp_analytics_landing_route: allowed(String(attribution.landingRoute||''), routeGroups),
bp_analytics_entry_surface: allowed(String(attribution.entrySurface||''), entrySurfaces),
bp_analytics_proxy_type: item ? item.proxy_type:'',
bp_analytics_package_size: item ? String(item.package_size):'',
bp_analytics_funnel_version: /^\d{4}-\d{2}-\d{2}\.\d+$/.test(String(config.funnelVersion||'')) ? String(config.funnelVersion):''
};
Object.keys(values).forEach(function (name){
var input=bridgeInput(name);
if(input) input.value=values[name];
});
});
}
window.BPAnalytics={
track: track,
captureIds: captureIds,
attribution: initialAttribution,
rememberItem: function (item){
var clean=sanitizeCommerceState(item);
return clean ? write(itemKey, clean):false;
},
lastItem: function (){
return read(itemKey, null);
},
flush: flush
};
if(document.readyState==='loading'){
document.addEventListener('DOMContentLoaded', fillCheckoutAttribution);
}else{
fillCheckoutAttribution();
}
document.addEventListener('click', function (event){
var link=event.target&&event.target.closest ? event.target.closest('[data-bp-action]'):null;
var contentId=link ? String(link.getAttribute('data-bp-action')||''):'';
if(!/^whois-(?:proxy-test|reputation-check|whois-guide|dedicated-plans)$/.test(contentId)) return;
track('select_content', { content_type: 'cta', content_id: contentId }, identifier('select_content'));
}, true);
initialAttribution();
flush();
window.setTimeout(flush, 250);
window.setTimeout(flush, 1000);
window.addEventListener('pageshow', flush);
['pointerdown', 'keydown', 'touchstart'].forEach(function (name){
window.addEventListener(name, function (){
window.setTimeout(flush, 0);
window.setTimeout(flush, 250);
}, { passive: true });
});
}());