@mate-academy/sourcebuster
Version:
Get sources of your site's visitors (utm / organic / referral / typein).
612 lines (491 loc) • 20.2 kB
JavaScript
describe('utm_type override', () => {
it('should override typ when utm_type is provided', () => {
setLocation('https://example.com/?utm_type=organic&utm_source=google&utm_medium=organic');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('organic');
});
it('should default to typ=utm when utm_type is not provided', () => {
setLocation('https://example.com/?utm_source=facebook&utm_medium=cpc');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('utm');
});
});
describe('traffic type detection', () => {
it('should set typ to utm for gclid parameter', () => {
setLocation('https://example.com/?gclid=abc123');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('utm');
expect(sbjs.get.current.src).toBe('google');
});
it('should set typ to organic when referrer is google.com', () => {
setLocation('https://example.com/');
setReferrer('https://www.google.com/');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('organic');
expect(sbjs.get.current.src).toBe('google');
});
it('should set typ to referral when referrer is non-search domain', () => {
setLocation('https://example.com/');
setReferrer('https://facebook.com/post');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('referral');
expect(sbjs.get.current.src).toBe('facebook.com');
expect(sbjs.get.current.mdm).toBe('referral');
});
it('should set typ to typein when no referrer and no UTM', () => {
setLocation('https://example.com/');
setReferrer('');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('typein');
expect(sbjs.get.current.src).toBe('(direct)');
expect(sbjs.get.current.mdm).toBe('(none)');
});
});
describe('cookie persistence', () => {
it('should store current visit data in sbjs_current cookie', () => {
setLocation('https://example.com/?utm_source=test');
const sbjs = require('./sourcebuster');
sbjs.init();
const cookie = decodeURIComponent(getCookie('sbjs_current'));
expect(cookie).toBeDefined();
expect(cookie).toContain('src=test');
});
it('should set sbjs_first only on first visit and never change it', () => {
setLocation('https://example.com/?utm_source=google');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.first.src).toBe('google');
jest.resetModules();
setLocation('https://example.com/?utm_source=facebook');
sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.first.src).toBe('google');
expect(sbjs.get.current.src).toBe('facebook');
});
});
describe('source overriding rules', () => {
it('should allow UTM to override previous referral source', () => {
setLocation('https://example.com/');
setReferrer('https://facebook.com/');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('referral');
jest.resetModules();
clearCookies();
setCookie('sbjs_current', 'typ=referral|||src=facebook.com|||mdm=referral|||cmp=(none)|||cnt=(none)|||trm=(none)');
setLocation('https://example.com/?utm_source=google');
setReferrer('');
sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('utm');
expect(sbjs.get.current.src).toBe('google');
});
it('should allow organic to override previous referral source', () => {
setLocation('https://example.com/');
setReferrer('https://facebook.com/');
let sbjs = require('./sourcebuster');
sbjs.init();
jest.resetModules();
clearCookies();
setCookie('sbjs_current', 'typ=referral|||src=facebook.com|||mdm=referral|||cmp=(none)|||cnt=(none)|||trm=(none)');
setLocation('https://example.com/');
setReferrer('https://www.google.com/');
sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('organic');
});
it('should not allow typein to override previous source', () => {
setLocation('https://example.com/?utm_source=google');
let sbjs = require('./sourcebuster');
sbjs.init();
jest.resetModules();
clearCookies();
setCookie('sbjs_current', 'typ=utm|||src=google|||mdm=cpc|||cmp=(none)|||cnt=(none)|||trm=(none)');
setLocation('https://example.com/');
setReferrer('');
sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.src).toBe('google');
});
it('should not allow referral to override within same session', () => {
setLocation('https://example.com/?utm_source=google');
let sbjs = require('./sourcebuster');
sbjs.init();
jest.resetModules();
setLocation('https://example.com/page2');
setReferrer('https://facebook.com/');
sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.src).toBe('google');
});
});
describe('UTM parameters capture', () => {
it('should capture all standard UTM parameters', () => {
setLocation('https://example.com/?utm_source=google&utm_medium=cpc&utm_campaign=summer&utm_content=banner&utm_term=shoes');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.src).toBe('google');
expect(sbjs.get.current.mdm).toBe('cpc');
expect(sbjs.get.current.cmp).toBe('summer');
expect(sbjs.get.current.cnt).toBe('banner');
expect(sbjs.get.current.trm).toBe('shoes');
});
it('should capture extended Google Ads UTM parameters', () => {
setLocation('https://example.com/?gclid=abc&utm_id=67890');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('utm');
expect(sbjs.get.current.src).toBe('google');
});
});
describe('session tracking', () => {
it('should increment page views within same session', () => {
setLocation('https://example.com/');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(parseInt(sbjs.get.session.pgs)).toBe(1);
jest.resetModules();
setLocation('https://example.com/about');
sbjs = require('./sourcebuster');
sbjs.init();
expect(parseInt(sbjs.get.session.pgs)).toBe(2);
});
it('should create new session when UTM parameters change', () => {
jest.useFakeTimers();
setLocation('https://example.com/?utm_source=google');
let sbjs = require('./sourcebuster');
sbjs.init();
const firstSessionId = sbjs.get.session.sid;
jest.advanceTimersByTime(1);
jest.resetModules();
setLocation('https://example.com/?utm_source=facebook');
sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.session.sid).toBeDefined();
expect(firstSessionId).toBeDefined();
expect(sbjs.get.session.sid).not.toBe(firstSessionId);
expect(parseInt(sbjs.get.session.pgs)).toBe(2);
jest.useRealTimers();
});
});
describe('visit counting', () => {
it('should increment visit counter only when session expires', () => {
setLocation('https://example.com/?utm_source=google');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(parseInt(sbjs.get.udata.vst)).toBe(1);
jest.resetModules();
setLocation('https://example.com/page2');
sbjs = require('./sourcebuster');
sbjs.init();
expect(parseInt(sbjs.get.udata.vst)).toBe(1);
jest.resetModules();
clearCookies();
setCookie('sbjs_current', 'typ=utm|||src=google|||mdm=cpc|||cmp=(none)|||cnt=(none)|||trm=(none)');
setCookie('sbjs_udata', 'vst=1|||uip=(none)|||uag=test');
setLocation('https://example.com/page3');
sbjs = require('./sourcebuster');
sbjs.init();
expect(parseInt(sbjs.get.udata.vst)).toBe(2);
});
});
describe('click ID storage', () => {
it('should store gclid in cookie when gclid param is present', () => {
setLocation('https://example.com/?gclid=abc123');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-gclid')).toBe('abc123');
});
it('should store gbraid in cookie when gbraid param is present', () => {
setLocation('https://example.com/?gbraid=gb123');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-gbraid')).toBe('gb123');
});
it('should store wbraid in cookie when wbraid param is present', () => {
setLocation('https://example.com/?wbraid=wb123');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-wbraid')).toBe('wb123');
});
it('should store fbclid in cookie when fbclid param is present', () => {
setLocation('https://example.com/?fbclid=fb456');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-fbclid')).toBe('fb456');
});
it('should store ttclid in cookie when ttclid param is present', () => {
setLocation('https://example.com/?ttclid=tt789');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-ttclid')).toBe('tt789');
});
it('should store sdclid in cookie when utm_source=sd param is present', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd123');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid')).toBe('sd123');
});
it('should store ksclid in cookie when ks_click_id param is present', () => {
setLocation('https://example.com/?ks_click_id=ks789');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-ksclid')).toBe('ks789');
});
it('should overwrite existing gclid when new gclid param arrives', () => {
setLocation('https://example.com/?gclid=gclid_old');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-gclid')).toBe('gclid_old');
jest.resetModules();
setLocation('https://example.com/?gclid=gclid_new');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-gclid')).toBe('gclid_new');
});
it('should overwrite existing gbraid when new gbraid param arrives', () => {
setLocation('https://example.com/?gbraid=gb_old');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-gbraid')).toBe('gb_old');
jest.resetModules();
setLocation('https://example.com/?gbraid=gb_new');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-gbraid')).toBe('gb_new');
});
it('should overwrite existing wbraid when new wbraid param arrives', () => {
setLocation('https://example.com/?wbraid=wb_old');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-wbraid')).toBe('wb_old');
jest.resetModules();
setLocation('https://example.com/?wbraid=wb_new');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-wbraid')).toBe('wb_new');
});
it('should overwrite existing fbclid when new fbclid param arrives', () => {
setLocation('https://example.com/?fbclid=fb_old');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-fbclid')).toBe('fb_old');
jest.resetModules();
setLocation('https://example.com/?fbclid=fb_new');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-fbclid')).toBe('fb_new');
});
it('should overwrite existing ttclid when new ttclid param arrives', () => {
setLocation('https://example.com/?ttclid=tt_old');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-ttclid')).toBe('tt_old');
jest.resetModules();
setLocation('https://example.com/?ttclid=tt_new');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-ttclid')).toBe('tt_new');
});
it('should overwrite existing sdclid when new sdclid param arrives', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd_old');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid')).toBe('sd_old');
jest.resetModules();
setLocation('https://example.com/?utm_source=sd&utm_term=sd_new');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid')).toBe('sd_new');
});
it('should overwrite existing ksclid when new ksclid param arrives', () => {
setLocation('https://example.com/?ks_click_id=ks_old');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-ksclid')).toBe('ks_old');
jest.resetModules();
setLocation('https://example.com/?ks_click_id=ks_new');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-ksclid')).toBe('ks_new');
});
it('should destroy sdclid and ksclid when gclid arrives', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd123');
let sbjs = require('./sourcebuster');
sbjs.init();
setCookie('_mate-ksclid', 'ks123');
jest.resetModules();
setLocation('https://example.com/?gclid=gclid456');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid') === undefined || getCookie('_mate-sdclid') === '').toBe(true);
expect(getCookie('_mate-ksclid') === undefined || getCookie('_mate-ksclid') === '').toBe(true);
expect(getCookie('_mate-gclid')).toBe('gclid456');
});
it('should destroy sdclid and ksclid when gbraid arrives', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd123');
let sbjs = require('./sourcebuster');
sbjs.init();
setCookie('_mate-ksclid', 'ks123');
jest.resetModules();
setLocation('https://example.com/?gbraid=gb456');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid') === undefined || getCookie('_mate-sdclid') === '').toBe(true);
expect(getCookie('_mate-ksclid') === undefined || getCookie('_mate-ksclid') === '').toBe(true);
expect(getCookie('_mate-gbraid')).toBe('gb456');
});
it('should destroy sdclid and ksclid when wbraid arrives', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd123');
let sbjs = require('./sourcebuster');
sbjs.init();
setCookie('_mate-ksclid', 'ks123');
jest.resetModules();
setLocation('https://example.com/?wbraid=wb456');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid') === undefined || getCookie('_mate-sdclid') === '').toBe(true);
expect(getCookie('_mate-ksclid') === undefined || getCookie('_mate-ksclid') === '').toBe(true);
expect(getCookie('_mate-wbraid')).toBe('wb456');
});
it('should destroy sdclid and ksclid when fbclid arrives', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd123');
let sbjs = require('./sourcebuster');
sbjs.init();
setCookie('_mate-ksclid', 'ks123');
jest.resetModules();
setLocation('https://example.com/?fbclid=fb456');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid') === undefined || getCookie('_mate-sdclid') === '').toBe(true);
expect(getCookie('_mate-ksclid') === undefined || getCookie('_mate-ksclid') === '').toBe(true);
expect(getCookie('_mate-fbclid')).toBe('fb456');
});
it('should destroy sdclid and ksclid when ttclid arrives', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd123');
let sbjs = require('./sourcebuster');
sbjs.init();
setCookie('_mate-ksclid', 'ks123');
jest.resetModules();
setLocation('https://example.com/?ttclid=tt456');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid') === undefined || getCookie('_mate-sdclid') === '').toBe(true);
expect(getCookie('_mate-ksclid') === undefined || getCookie('_mate-ksclid') === '').toBe(true);
expect(getCookie('_mate-ttclid')).toBe('tt456');
});
it('should destroy ksclid when sdclid arrives', () => {
setLocation('https://example.com/?ks_click_id=ks123');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-ksclid')).toBe('ks123');
jest.resetModules();
setLocation('https://example.com/?utm_source=sd&utm_term=sd456');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-ksclid') === undefined || getCookie('_mate-ksclid') === '').toBe(true);
expect(getCookie('_mate-sdclid')).toBe('sd456');
});
it('should destroy sdclid when ksclid arrives', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd123');
let sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid')).toBe('sd123');
jest.resetModules();
setLocation('https://example.com/?ks_click_id=ks456');
sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookie('_mate-sdclid') === undefined || getCookie('_mate-sdclid') === '').toBe(true);
expect(getCookie('_mate-ksclid')).toBe('ks456');
});
});
describe('affiliate cookie lifetime', () => {
it('should set sdclid cookie with 30-day lifetime', () => {
setLocation('https://example.com/?utm_source=sd&utm_term=sd123');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookieLifetimeDays('_mate-sdclid')).toBe(30);
});
it('should set ksclid cookie with 30-day lifetime', () => {
setLocation('https://example.com/?ks_click_id=ks789');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookieLifetimeDays('_mate-ksclid')).toBe(30);
});
it('should set gclid cookie with default 6-month lifetime', () => {
setLocation('https://example.com/?gclid=gclid123');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(getCookieLifetimeDays('_mate-gclid')).toBe(180);
});
});
describe('organic source detection', () => {
it('should detect Bing organic traffic', () => {
setLocation('https://example.com/');
setReferrer('https://www.bing.com/search?q=test');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('organic');
expect(sbjs.get.current.src).toBe('bing');
});
it('should detect Yahoo organic traffic', () => {
setLocation('https://example.com/');
setReferrer('https://search.yahoo.com/search?p=test');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.typ).toBe('organic');
expect(sbjs.get.current.src).toBe('yahoo');
});
});
describe('referral content tracking', () => {
it('should store referrer path as utm_content for referral traffic', () => {
setLocation('https://example.com/');
setReferrer('https://facebook.com/some/post/path');
const sbjs = require('./sourcebuster');
sbjs.init();
expect(sbjs.get.current.cnt).toBe('/some/post/path');
});
});
describe('custom configuration', () => {
it('should respect custom typein attributes', () => {
setLocation('https://example.com/');
setReferrer('');
const sbjs = require('./sourcebuster');
sbjs.init({
typein_attributes: {
source: 'custom_direct',
medium: 'custom_none'
}
});
expect(sbjs.get.current.src).toBe('custom_direct');
expect(sbjs.get.current.mdm).toBe('custom_none');
});
});
describe('sbjs:loaded event', () => {
it('should dispatch sbjs:loaded event when module loads', () => {
const eventHandler = jest.fn();
window.addEventListener('sbjs:loaded', eventHandler);
jest.resetModules();
require('./sourcebuster');
expect(eventHandler).toHaveBeenCalledTimes(1);
expect(eventHandler.mock.calls[0][0].type).toBe('sbjs:loaded');
window.removeEventListener('sbjs:loaded', eventHandler);
});
it('should dispatch sbjs:loaded as CustomEvent', () => {
let receivedEvent = null;
const eventHandler = (event) => {
receivedEvent = event;
};
window.addEventListener('sbjs:loaded', eventHandler);
jest.resetModules();
require('./sourcebuster');
expect(receivedEvent).toBeInstanceOf(CustomEvent);
window.removeEventListener('sbjs:loaded', eventHandler);
});
});