saasco-sdk 0.1.42 → 0.1.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.js +427 -119
- package/index.esm.js +426 -119
- package/package.json +1 -1
- package/src/lib/analytics.d.ts +17 -1
- package/src/lib/integrations/facebook-pixel.d.ts +1 -1
- package/src/lib/integrations/index.d.ts +1 -0
- package/src/lib/integrations/integration-manager.d.ts +5 -11
- package/src/lib/integrations/pinterest-tag.d.ts +37 -0
- package/src/lib/integrations/tiktok-pixel.d.ts +1 -1
- package/src/lib/utils/getIntegrationLoggerLevel.d.ts +8 -0
- package/src/lib/utils/index.d.ts +1 -0
- package/src/lib/utils/logger.d.ts +9 -2
package/index.cjs.js
CHANGED
|
@@ -4,11 +4,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var tslib = require('tslib');
|
|
6
6
|
var psl = require('psl');
|
|
7
|
-
var jsSha256 = require('js-sha256');
|
|
8
7
|
var uuid$1 = require('@lukeed/uuid');
|
|
8
|
+
var jsSha256 = require('js-sha256');
|
|
9
9
|
var zod = require('zod');
|
|
10
10
|
|
|
11
|
-
var version = "0.1.
|
|
11
|
+
var version = "0.1.44";
|
|
12
12
|
|
|
13
13
|
const timezones = {
|
|
14
14
|
'Asia/Barnaul': 'RU',
|
|
@@ -555,26 +555,117 @@ function getBrowserContext() {
|
|
|
555
555
|
};
|
|
556
556
|
}
|
|
557
557
|
|
|
558
|
-
|
|
559
|
-
|
|
558
|
+
var LogLevel;
|
|
559
|
+
(function (LogLevel) {
|
|
560
|
+
LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
|
|
561
|
+
LogLevel[LogLevel["WARN"] = 1] = "WARN";
|
|
562
|
+
LogLevel[LogLevel["INFO"] = 2] = "INFO";
|
|
563
|
+
LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
|
|
564
|
+
})(LogLevel || (LogLevel = {}));
|
|
565
|
+
class AnalyticsLogger {
|
|
566
|
+
constructor(config) {
|
|
567
|
+
this.config = config;
|
|
568
|
+
}
|
|
569
|
+
debug(...args) {
|
|
570
|
+
if (this.config.level < LogLevel.DEBUG) return;
|
|
571
|
+
const icon = '◍';
|
|
572
|
+
const message = `${icon} ${this.config.label}`;
|
|
573
|
+
console.debug(`%c ${message}`, `background: #eee; color: #000; padding-right: 6px; border-radius: 2px;`, ...args);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Log debug information
|
|
577
|
+
*/
|
|
578
|
+
info(...args) {
|
|
579
|
+
if (this.config.level < LogLevel.INFO) return;
|
|
580
|
+
const icon = '◍';
|
|
581
|
+
const message = `${icon} ${this.config.label}`;
|
|
582
|
+
console.info(`%c ${message}`, `background: #eee; color: #000; padding-right: 6px; border-radius: 2px;`, ...args);
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Log warning information
|
|
586
|
+
*/
|
|
587
|
+
warn(...args) {
|
|
588
|
+
if (this.config.level < LogLevel.WARN) return;
|
|
589
|
+
const icon = '◍';
|
|
590
|
+
const message = `${icon} ${this.config.label}`;
|
|
591
|
+
console.warn(`%c ${message}`, `background: #ffa500; color: #000; padding-right: 6px; border-radius: 2px;`, ...args);
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Log error information
|
|
595
|
+
*/
|
|
596
|
+
error(...args) {
|
|
597
|
+
const icon = '◍';
|
|
598
|
+
const message = `${icon} ${this.config.label} Error`;
|
|
599
|
+
console.error(`%c ${message}`, 'background: red; color: white; padding-right: 6px; border-radius: 2px;', ...args);
|
|
600
|
+
return {
|
|
601
|
+
success: false,
|
|
602
|
+
message: args.join(' ')
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const isBrowser$4 = typeof window !== 'undefined';
|
|
608
|
+
const isServer$4 = !isBrowser$4;
|
|
609
|
+
/**
|
|
610
|
+
* Get the logger level for a specific integration
|
|
611
|
+
* Supports URL parameters like saasco-debug-{integration-type}=true
|
|
612
|
+
* If debug is true or URL param is true, sets level to DEBUG (3), otherwise WARN
|
|
613
|
+
*/
|
|
614
|
+
function getIntegrationLoggerLevel(integrationName, debug) {
|
|
615
|
+
// Check URL parameters for debug overrides (browser only)
|
|
616
|
+
let urlDebug = false;
|
|
617
|
+
if (!isServer$4) {
|
|
618
|
+
try {
|
|
619
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
620
|
+
const paramName = `saasco-debug-${integrationName}`;
|
|
621
|
+
const paramValue = urlParams.get(paramName);
|
|
622
|
+
if (paramValue === 'true') {
|
|
623
|
+
urlDebug = true;
|
|
624
|
+
}
|
|
625
|
+
} catch (error) {
|
|
626
|
+
// Ignore URL parsing errors
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
// URL parameters override config, config overrides default (WARN)
|
|
630
|
+
return urlDebug || debug ? LogLevel.DEBUG : LogLevel.WARN;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Generate a collision-resistant UUID
|
|
635
|
+
* Uses lukeed's UUID v4 implementation for consistent, fast UUID generation
|
|
636
|
+
*/
|
|
637
|
+
function uuid() {
|
|
638
|
+
return uuid$1.v4();
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const isBrowser$3 = typeof window !== 'undefined';
|
|
642
|
+
const isServer$3 = !isBrowser$3;
|
|
560
643
|
const standardFacebookEvents = ['AddPaymentInfo', 'AddToCart', 'AddToWishlist', 'CompleteRegistration', 'Contact', 'CustomizeProduct', 'Donate', 'FindLocation', 'InitiateCheckout', 'Lead', 'Purchase', 'Schedule', 'Search', 'StartTrial', 'SubmitApplication', 'Subscribe', 'ViewContent', 'PageView'];
|
|
561
644
|
/**
|
|
562
645
|
* Create a Facebook Pixel integration instance
|
|
563
646
|
*/
|
|
564
|
-
function createFacebookPixelIntegration(config) {
|
|
647
|
+
function createFacebookPixelIntegration(config, debug) {
|
|
565
648
|
let isPixelReady = false;
|
|
649
|
+
// Create integration logger
|
|
650
|
+
const integrationLoggerLevel = getIntegrationLoggerLevel('facebook-pixel', debug);
|
|
651
|
+
const logger = new AnalyticsLogger({
|
|
652
|
+
level: integrationLoggerLevel,
|
|
653
|
+
label: 'Saasco facebook-pixel'
|
|
654
|
+
});
|
|
566
655
|
return {
|
|
567
656
|
name: 'facebook-pixel',
|
|
568
657
|
environments: ['client'],
|
|
569
658
|
init: () => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
570
|
-
if (isServer$
|
|
571
|
-
|
|
572
|
-
// This allows the integration to be registered but remain inactive
|
|
659
|
+
if (isServer$3) {
|
|
660
|
+
logger.debug('Facebook Pixel init skipped on server');
|
|
573
661
|
return;
|
|
574
662
|
}
|
|
663
|
+
logger.info('Initializing Facebook Pixel', {
|
|
664
|
+
pixelId: config.pixelId
|
|
665
|
+
});
|
|
575
666
|
// Check if Facebook Pixel is already loaded
|
|
576
667
|
if (window.fbq || window._fbq) {
|
|
577
|
-
|
|
668
|
+
logger.warn('Facebook Pixel is already initialized');
|
|
578
669
|
isPixelReady = true;
|
|
579
670
|
return;
|
|
580
671
|
}
|
|
@@ -597,9 +688,11 @@ function createFacebookPixelIntegration(config) {
|
|
|
597
688
|
// Add load event listener
|
|
598
689
|
t.onload = () => {
|
|
599
690
|
isPixelReady = true;
|
|
691
|
+
logger.info('Facebook Pixel script loaded successfully');
|
|
600
692
|
resolve();
|
|
601
693
|
};
|
|
602
694
|
t.onerror = () => {
|
|
695
|
+
logger.error('Failed to load Facebook Pixel script');
|
|
603
696
|
reject(new Error('Failed to load Facebook Pixel script'));
|
|
604
697
|
};
|
|
605
698
|
s = b.getElementsByTagName(e)[0];
|
|
@@ -610,33 +703,56 @@ function createFacebookPixelIntegration(config) {
|
|
|
610
703
|
// Allow duplicate PageView events
|
|
611
704
|
window.fbq.allowDuplicatePageViews = true;
|
|
612
705
|
if (config.automaticConfiguration === false) {
|
|
706
|
+
logger.debug('Disabling automatic configuration');
|
|
613
707
|
window.fbq('set', 'autoConfig', false, config.pixelId);
|
|
614
708
|
}
|
|
615
709
|
// Initialize pixel
|
|
710
|
+
logger.debug('Initializing Facebook Pixel with ID', config.pixelId);
|
|
616
711
|
window.fbq('init', config.pixelId);
|
|
617
712
|
// If script loads synchronously, mark as ready
|
|
618
713
|
if (window.fbq && typeof window.fbq === 'function') {
|
|
619
714
|
isPixelReady = true;
|
|
715
|
+
logger.info('Facebook Pixel initialized synchronously');
|
|
620
716
|
resolve();
|
|
621
717
|
}
|
|
622
718
|
} catch (error) {
|
|
719
|
+
logger.error('Error during Facebook Pixel initialization', error);
|
|
623
720
|
reject(error);
|
|
624
721
|
}
|
|
625
722
|
});
|
|
626
723
|
}),
|
|
627
724
|
track: (eventName, properties, context) => {
|
|
628
|
-
if (!isPixelReady || !window.fbq)
|
|
725
|
+
if (!isPixelReady || !window.fbq) {
|
|
726
|
+
logger.warn('Facebook Pixel not ready, skipping track event', {
|
|
727
|
+
eventName
|
|
728
|
+
});
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
629
731
|
const fbEventName = getFacebookEventName(eventName, config.eventMapping);
|
|
630
732
|
const eventsWithParams = ['Purchase', 'StartTrial', 'Subscribe'];
|
|
631
733
|
const isStandardEvent = standardFacebookEvents.includes(fbEventName);
|
|
632
734
|
const trackType = isStandardEvent ? 'track' : 'trackCustom';
|
|
735
|
+
logger.debug('Tracking Facebook Pixel event', {
|
|
736
|
+
originalEvent: eventName,
|
|
737
|
+
fbEventName,
|
|
738
|
+
trackType,
|
|
739
|
+
isStandardEvent,
|
|
740
|
+
properties
|
|
741
|
+
});
|
|
633
742
|
if (eventsWithParams.includes(fbEventName) && properties) {
|
|
634
743
|
const fbParams = {};
|
|
635
744
|
if (properties['value'] !== undefined) fbParams['value'] = properties['value'];
|
|
636
745
|
if (properties['currency'] !== undefined) fbParams['currency'] = properties['currency'];
|
|
637
746
|
if (properties['predicted_ltv'] !== undefined) fbParams['predicted_ltv'] = properties['predicted_ltv'];
|
|
747
|
+
logger.info('Tracking Facebook Pixel event with parameters', {
|
|
748
|
+
event: fbEventName,
|
|
749
|
+
params: fbParams
|
|
750
|
+
});
|
|
638
751
|
window.fbq(trackType, fbEventName, fbParams);
|
|
639
752
|
} else {
|
|
753
|
+
logger.info('Tracking Facebook Pixel event', {
|
|
754
|
+
event: fbEventName
|
|
755
|
+
});
|
|
640
756
|
window.fbq(trackType, fbEventName);
|
|
641
757
|
}
|
|
642
758
|
},
|
|
@@ -802,7 +918,7 @@ function coerceMetaConversionsAmValues(properties) {
|
|
|
802
918
|
coerceFrom,
|
|
803
919
|
transform
|
|
804
920
|
} of coerce) {
|
|
805
|
-
const foundValue = findFirstProperty$
|
|
921
|
+
const foundValue = findFirstProperty$2(properties, coerceFrom);
|
|
806
922
|
if (foundValue !== null && transform) {
|
|
807
923
|
const transformedValue = transform(foundValue);
|
|
808
924
|
if (transformedValue) {
|
|
@@ -814,6 +930,183 @@ function coerceMetaConversionsAmValues(properties) {
|
|
|
814
930
|
}
|
|
815
931
|
return result;
|
|
816
932
|
}
|
|
933
|
+
function findFirstProperty$2(properties, keys) {
|
|
934
|
+
for (const key of keys) {
|
|
935
|
+
if (properties[key] !== undefined) {
|
|
936
|
+
return properties[key];
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return null;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
const isBrowser$2 = typeof window !== 'undefined';
|
|
943
|
+
const isServer$2 = !isBrowser$2;
|
|
944
|
+
/**
|
|
945
|
+
* Standard Pinterest events
|
|
946
|
+
* Reference: https://www.pinterest.com/_/_/help/business/article/event-code
|
|
947
|
+
*/
|
|
948
|
+
const standardPinterestEvents = ['checkout', 'addtocart', 'pagevisit', 'signup', 'watchvideo', 'lead', 'search', 'viewcategory', 'custom', 'addpaymentinfo', 'addtowishlist', 'initiatecheckout', 'subscribe', 'viewcontent'];
|
|
949
|
+
/**
|
|
950
|
+
* Create a Pinterest Tag integration instance
|
|
951
|
+
* Documentation: https://help.pinterest.com/en/business/article/install-the-pinterest-tag
|
|
952
|
+
*/
|
|
953
|
+
function createPinterestTagIntegration(config, debug) {
|
|
954
|
+
let isTagReady = false;
|
|
955
|
+
// Create integration logger
|
|
956
|
+
const integrationLoggerLevel = getIntegrationLoggerLevel('pinterest-tag', debug);
|
|
957
|
+
const logger = new AnalyticsLogger({
|
|
958
|
+
level: integrationLoggerLevel,
|
|
959
|
+
label: 'Saasco Pinterest Tag'
|
|
960
|
+
});
|
|
961
|
+
return {
|
|
962
|
+
name: 'pinterest-tag',
|
|
963
|
+
environments: ['client'],
|
|
964
|
+
init: context => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
965
|
+
if (isServer$2) {
|
|
966
|
+
logger.debug('Pinterest Tag init skipped on server');
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
969
|
+
logger.info('Initializing Pinterest Tag', {
|
|
970
|
+
tagId: config.tagId
|
|
971
|
+
});
|
|
972
|
+
// Check if Pinterest Tag is already loaded
|
|
973
|
+
if (window.pintrk || window._pintrk) {
|
|
974
|
+
logger.warn('Pinterest Tag is already initialized');
|
|
975
|
+
isTagReady = true;
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
// Initialize Pinterest Tag
|
|
979
|
+
return new Promise((resolve, reject) => {
|
|
980
|
+
try {
|
|
981
|
+
// Pinterest Tag initialization script
|
|
982
|
+
// Reference: https://help.pinterest.com/en/business/article/install-the-base-code
|
|
983
|
+
(function (e) {
|
|
984
|
+
if (!window.pintrk) {
|
|
985
|
+
window.pintrk = function () {
|
|
986
|
+
window.pintrk.queue.push(Array.prototype.slice.call(arguments));
|
|
987
|
+
};
|
|
988
|
+
const n = window.pintrk;
|
|
989
|
+
n.queue = [];
|
|
990
|
+
n.version = '3.0';
|
|
991
|
+
const t = document.createElement('script');
|
|
992
|
+
t.async = true;
|
|
993
|
+
t.src = e;
|
|
994
|
+
// Add load event listener
|
|
995
|
+
t.onload = () => {
|
|
996
|
+
// base script is loaded; now (re)load tag + fire page via runtime
|
|
997
|
+
window.pintrk('load', config.tagId);
|
|
998
|
+
// initialize the tag
|
|
999
|
+
window.pintrk('page');
|
|
1000
|
+
// delay isTagReady to ensure the tag is loaded before sending events
|
|
1001
|
+
setTimeout(() => {
|
|
1002
|
+
logger.debug('Pinterest Tag initialized');
|
|
1003
|
+
isTagReady = true;
|
|
1004
|
+
resolve();
|
|
1005
|
+
}, 500);
|
|
1006
|
+
};
|
|
1007
|
+
t.onerror = () => {
|
|
1008
|
+
logger.error('Failed to load Pinterest Tag script');
|
|
1009
|
+
reject(new Error('Failed to load Pinterest Tag script'));
|
|
1010
|
+
};
|
|
1011
|
+
const r = document.getElementsByTagName('script')[0];
|
|
1012
|
+
r.parentNode.insertBefore(t, r);
|
|
1013
|
+
}
|
|
1014
|
+
})('https://s.pinimg.com/ct/core.js');
|
|
1015
|
+
} catch (error) {
|
|
1016
|
+
logger.error('Failed to initialize Pinterest Tag', error);
|
|
1017
|
+
reject(error);
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1020
|
+
}),
|
|
1021
|
+
track: (eventName, properties, context) => {
|
|
1022
|
+
if (!isTagReady || !window.pintrk) return;
|
|
1023
|
+
const pinterestEventName = getPinterestEventName(eventName, config.eventMapping);
|
|
1024
|
+
const eventData = buildEventData(properties);
|
|
1025
|
+
// Get enhanced matching data from properties
|
|
1026
|
+
const enhancedMatchData = getPinterestEnhancedMatchData(context || {});
|
|
1027
|
+
logger.debug('Tracking event', {
|
|
1028
|
+
eventName,
|
|
1029
|
+
pinterestEventName,
|
|
1030
|
+
eventData,
|
|
1031
|
+
enhancedMatchData
|
|
1032
|
+
});
|
|
1033
|
+
// Combine event data with enhanced matching data
|
|
1034
|
+
const finalEventData = Object.assign(Object.assign({}, eventData), enhancedMatchData);
|
|
1035
|
+
// Track the event
|
|
1036
|
+
window.pintrk('track', pinterestEventName, finalEventData);
|
|
1037
|
+
},
|
|
1038
|
+
identify: (userId, properties, context) => {
|
|
1039
|
+
// Identify not supported with pinterest tag
|
|
1040
|
+
logger.debug('Identify not supported with pinterest tag', {
|
|
1041
|
+
userId,
|
|
1042
|
+
properties,
|
|
1043
|
+
context
|
|
1044
|
+
});
|
|
1045
|
+
window.pintrk('set', {
|
|
1046
|
+
external_id: userId
|
|
1047
|
+
});
|
|
1048
|
+
window.pintrk('set', {
|
|
1049
|
+
em: properties === null || properties === void 0 ? void 0 : properties['email']
|
|
1050
|
+
});
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
function getPinterestEventName(eventName, eventMapping) {
|
|
1056
|
+
// Convert default saasco Page View event by default
|
|
1057
|
+
if (eventName === 'Page View') return 'pagevisit';
|
|
1058
|
+
if (!eventMapping) return eventName.toLowerCase();
|
|
1059
|
+
return eventMapping[eventName] || eventName.toLowerCase();
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Build event data for Pinterest tracking
|
|
1063
|
+
* Reference: https://www.pinterest.com/_/_/help/business/article/event-code
|
|
1064
|
+
*/
|
|
1065
|
+
function buildEventData(properties) {
|
|
1066
|
+
if (!properties) return {};
|
|
1067
|
+
const eventData = {};
|
|
1068
|
+
// Map common properties to Pinterest event data
|
|
1069
|
+
if (properties['event_id']) eventData['event_id'] = properties['event_id'];
|
|
1070
|
+
if (properties['value']) eventData['value'] = properties['value'];
|
|
1071
|
+
if (properties['currency']) eventData['currency'] = properties['currency'];
|
|
1072
|
+
if (properties['order_quantity']) eventData['order_quantity'] = properties['order_quantity'];
|
|
1073
|
+
if (properties['order_id']) eventData['order_id'] = properties['order_id'];
|
|
1074
|
+
if (properties['promo_code']) eventData['promo_code'] = properties['promo_code'];
|
|
1075
|
+
if (properties['property']) eventData['property'] = properties['property'];
|
|
1076
|
+
if (properties['search_query']) eventData['search_query'] = properties['search_query'];
|
|
1077
|
+
if (properties['video_title']) eventData['video_title'] = properties['video_title'];
|
|
1078
|
+
if (properties['lead_type']) eventData['lead_type'] = properties['lead_type'];
|
|
1079
|
+
if (properties['product_category']) eventData['product_category'] = properties['product_category'];
|
|
1080
|
+
// Handle line items for e-commerce tracking
|
|
1081
|
+
if (properties['line_items'] && Array.isArray(properties['line_items'])) {
|
|
1082
|
+
eventData['line_items'] = properties['line_items'];
|
|
1083
|
+
}
|
|
1084
|
+
// Generate event_id if not provided
|
|
1085
|
+
if (!eventData['event_id']) {
|
|
1086
|
+
eventData['event_id'] = uuid();
|
|
1087
|
+
}
|
|
1088
|
+
return eventData;
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Get Pinterest Enhanced Matching values from properties
|
|
1092
|
+
* Reference: https://help.pinterest.com/en/business/article/enhanced-match
|
|
1093
|
+
*/
|
|
1094
|
+
function getPinterestEnhancedMatchData(properties) {
|
|
1095
|
+
const enhancedMatch = {};
|
|
1096
|
+
// Email
|
|
1097
|
+
const email = findFirstProperty$1(properties, ['email', 'user_email', 'userEmail', 'email_address', 'emailAddress', 'e_mail', 'E_Mail', 'mail', 'Mail', 'contact_email', 'contactEmail', 'primary_email', 'primaryEmail']);
|
|
1098
|
+
if (email && typeof email === 'string') {
|
|
1099
|
+
// Pinterest expects hashed email for enhanced matching
|
|
1100
|
+
const normalizedEmail = email.trim().toLowerCase();
|
|
1101
|
+
enhancedMatch.em = normalizedEmail;
|
|
1102
|
+
}
|
|
1103
|
+
// External ID (User ID)
|
|
1104
|
+
const externalId = findFirstProperty$1(properties, ['external_id', 'externalId', 'user_id', 'userId', 'id', 'distinctId', 'distinct_id', 'customer_id', 'customerId', 'member_id', 'memberId']);
|
|
1105
|
+
if (externalId) {
|
|
1106
|
+
enhancedMatch.external_id = String(externalId);
|
|
1107
|
+
}
|
|
1108
|
+
return enhancedMatch;
|
|
1109
|
+
}
|
|
817
1110
|
function findFirstProperty$1(properties, keys) {
|
|
818
1111
|
for (const key of keys) {
|
|
819
1112
|
if (properties[key] !== undefined) {
|
|
@@ -849,20 +1142,28 @@ const standardTikTokEvents = ['AddPaymentInfo', 'AddToCart', 'AddToWishlist', 'A
|
|
|
849
1142
|
/**
|
|
850
1143
|
* Create a TikTok Pixel integration instance
|
|
851
1144
|
*/
|
|
852
|
-
function createTikTokPixelIntegration(config) {
|
|
1145
|
+
function createTikTokPixelIntegration(config, debug) {
|
|
853
1146
|
let isPixelReady = false;
|
|
1147
|
+
// Create integration logger
|
|
1148
|
+
const integrationLoggerLevel = getIntegrationLoggerLevel('tiktok-pixel', debug);
|
|
1149
|
+
const logger = new AnalyticsLogger({
|
|
1150
|
+
level: integrationLoggerLevel,
|
|
1151
|
+
label: 'Saasco tiktok-pixel'
|
|
1152
|
+
});
|
|
854
1153
|
return {
|
|
855
1154
|
name: 'tiktok-pixel',
|
|
856
1155
|
environments: ['client'],
|
|
857
1156
|
init: () => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
858
1157
|
if (isServer$1) {
|
|
859
|
-
|
|
860
|
-
// This allows the integration to be registered but remain inactive
|
|
1158
|
+
logger.debug('TikTok Pixel init skipped on server');
|
|
861
1159
|
return;
|
|
862
1160
|
}
|
|
1161
|
+
logger.info('Initializing TikTok Pixel', {
|
|
1162
|
+
pixelId: config.pixelId
|
|
1163
|
+
});
|
|
863
1164
|
// Check if TikTok Pixel is already loaded
|
|
864
1165
|
if (window.ttq) {
|
|
865
|
-
|
|
1166
|
+
logger.warn('TikTok Pixel is already initialized');
|
|
866
1167
|
isPixelReady = true;
|
|
867
1168
|
return;
|
|
868
1169
|
}
|
|
@@ -913,7 +1214,6 @@ function createTikTokPixelIntegration(config) {
|
|
|
913
1214
|
ttq.load(config.pixelId, config.testMode ? {
|
|
914
1215
|
test_mode: true
|
|
915
1216
|
} : undefined);
|
|
916
|
-
ttq.page();
|
|
917
1217
|
// If script loads synchronously, mark as ready
|
|
918
1218
|
if (window.ttq && typeof window.ttq === 'function') {
|
|
919
1219
|
isPixelReady = true;
|
|
@@ -1088,69 +1388,9 @@ function mapTikTokEventParameters(eventName, properties) {
|
|
|
1088
1388
|
return Object.keys(params).length > 0 ? params : null;
|
|
1089
1389
|
}
|
|
1090
1390
|
|
|
1091
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1092
|
-
class AnalyticsLogger {
|
|
1093
|
-
constructor(config) {
|
|
1094
|
-
this.config = config;
|
|
1095
|
-
}
|
|
1096
|
-
/**
|
|
1097
|
-
* Log debug information
|
|
1098
|
-
*/
|
|
1099
|
-
log(...args) {
|
|
1100
|
-
if (!this.config.debug) return;
|
|
1101
|
-
const icon = '◍';
|
|
1102
|
-
const message = `${icon} ${this.config.label}`;
|
|
1103
|
-
console.info(`%c ${message}`, `background: #eee; color: #000; padding-right: 6px; border-radius: 2px;`, ...args);
|
|
1104
|
-
}
|
|
1105
|
-
/**
|
|
1106
|
-
* Log warning information
|
|
1107
|
-
*/
|
|
1108
|
-
warn(...args) {
|
|
1109
|
-
if (!this.config.debug) return;
|
|
1110
|
-
const icon = '◍';
|
|
1111
|
-
const message = `${icon} ${this.config.label}`;
|
|
1112
|
-
console.warn(`%c ${message}`, `background: #ffa500; color: #000; padding-right: 6px; border-radius: 2px;`, ...args);
|
|
1113
|
-
}
|
|
1114
|
-
/**
|
|
1115
|
-
* Log error information
|
|
1116
|
-
*/
|
|
1117
|
-
error(...args) {
|
|
1118
|
-
const icon = '◍';
|
|
1119
|
-
const message = `${icon} ${this.config.label} Error`;
|
|
1120
|
-
console.error(`%c ${message}`, 'background: red; color: white; padding-right: 6px; border-radius: 2px;', ...args);
|
|
1121
|
-
return {
|
|
1122
|
-
success: false,
|
|
1123
|
-
message: args.join(' ')
|
|
1124
|
-
};
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
/**
|
|
1129
|
-
* Generate a collision-resistant UUID
|
|
1130
|
-
* Uses lukeed's UUID v4 implementation for consistent, fast UUID generation
|
|
1131
|
-
*/
|
|
1132
|
-
function uuid() {
|
|
1133
|
-
return uuid$1.v4();
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
1391
|
/*
|
|
1137
1392
|
Minimal analytics integration manager (v0)
|
|
1138
1393
|
*/
|
|
1139
|
-
class Logger {
|
|
1140
|
-
constructor(label = 'Analytics', debug = false) {
|
|
1141
|
-
this.label = label;
|
|
1142
|
-
this.debug = debug;
|
|
1143
|
-
}
|
|
1144
|
-
log(...args) {
|
|
1145
|
-
if (this.debug) console.log(`[${this.label}]`, ...args);
|
|
1146
|
-
}
|
|
1147
|
-
warn(...args) {
|
|
1148
|
-
console.warn(`[${this.label}]`, ...args);
|
|
1149
|
-
}
|
|
1150
|
-
error(...args) {
|
|
1151
|
-
console.error(`[${this.label}]`, ...args);
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
1394
|
class IntegrationManager {
|
|
1155
1395
|
constructor(config = {}) {
|
|
1156
1396
|
var _a, _b, _c, _d;
|
|
@@ -1158,14 +1398,14 @@ class IntegrationManager {
|
|
|
1158
1398
|
this.integrations = new Map();
|
|
1159
1399
|
this.globalQueue = [];
|
|
1160
1400
|
this.config = {
|
|
1161
|
-
|
|
1401
|
+
loggerLevel: (_a = config.loggerLevel) !== null && _a !== void 0 ? _a : LogLevel.ERROR,
|
|
1162
1402
|
maxQueueSize: (_b = config.maxQueueSize) !== null && _b !== void 0 ? _b : 200,
|
|
1163
1403
|
maxIntegrationWaitTime: (_c = config.maxIntegrationWaitTime) !== null && _c !== void 0 ? _c : 10000,
|
|
1164
1404
|
flushInterval: (_d = config.flushInterval) !== null && _d !== void 0 ? _d : 5000
|
|
1165
1405
|
};
|
|
1166
1406
|
this.logger = new AnalyticsLogger({
|
|
1167
1407
|
label: 'Saasco Integrations Debug',
|
|
1168
|
-
|
|
1408
|
+
level: this.config.loggerLevel
|
|
1169
1409
|
});
|
|
1170
1410
|
this.initTime = Date.now();
|
|
1171
1411
|
this.currentEnvironment = typeof window !== 'undefined' ? 'client' : 'server';
|
|
@@ -1178,7 +1418,7 @@ class IntegrationManager {
|
|
|
1178
1418
|
setContext(next) {
|
|
1179
1419
|
this.context = Object.assign(Object.assign({}, this.context), next);
|
|
1180
1420
|
// Only log if we are setting something
|
|
1181
|
-
if (Object.keys(this.context).length > 0) this.logger.
|
|
1421
|
+
if (Object.keys(this.context).length > 0) this.logger.info('setContext', this.context);
|
|
1182
1422
|
}
|
|
1183
1423
|
/**
|
|
1184
1424
|
* Register and init an integration. When init resolves, we mark it ready and
|
|
@@ -1186,17 +1426,18 @@ class IntegrationManager {
|
|
|
1186
1426
|
*/
|
|
1187
1427
|
registerIntegration(integration) {
|
|
1188
1428
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1429
|
+
this.logger.debug('Register integrations', this.integrations);
|
|
1189
1430
|
if (this.integrations.has(integration.name)) {
|
|
1190
|
-
this.logger.warn(`
|
|
1431
|
+
this.logger.warn(`Integration already registered: ${integration.name}`);
|
|
1191
1432
|
return;
|
|
1192
1433
|
}
|
|
1193
1434
|
// Check environment compatibility
|
|
1194
1435
|
const isCompatible = integration.environments.includes(this.currentEnvironment);
|
|
1195
1436
|
if (!isCompatible) {
|
|
1196
|
-
this.logger.warn(`
|
|
1437
|
+
this.logger.warn(`Skipping ${integration.name}: requires ${integration.environments.join(' or ')} but running in ${this.currentEnvironment}`);
|
|
1197
1438
|
return;
|
|
1198
1439
|
}
|
|
1199
|
-
this.logger.
|
|
1440
|
+
this.logger.debug(`Registering ${integration.name}`);
|
|
1200
1441
|
const state = {
|
|
1201
1442
|
integration,
|
|
1202
1443
|
status: 'idle'
|
|
@@ -1205,17 +1446,21 @@ class IntegrationManager {
|
|
|
1205
1446
|
if (integration.init) {
|
|
1206
1447
|
try {
|
|
1207
1448
|
state.status = 'loading';
|
|
1208
|
-
|
|
1449
|
+
const startTime = Date.now();
|
|
1450
|
+
this.logger.debug(`Initializing ${integration.name}`);
|
|
1451
|
+
yield integration.init(this.context);
|
|
1209
1452
|
state.status = 'ready';
|
|
1210
|
-
|
|
1453
|
+
const endTime = Date.now();
|
|
1454
|
+
const duration = endTime - startTime;
|
|
1455
|
+
this.logger.debug(`Integration ${integration.name} ready in ${duration}ms`);
|
|
1211
1456
|
this.flush();
|
|
1212
1457
|
} catch (e) {
|
|
1213
1458
|
state.status = 'error';
|
|
1214
|
-
this.logger.error(`
|
|
1459
|
+
this.logger.error(`Failed to init ${integration.name}`, e);
|
|
1215
1460
|
}
|
|
1216
1461
|
} else {
|
|
1217
1462
|
state.status = 'ready';
|
|
1218
|
-
this.logger.
|
|
1463
|
+
this.logger.info(`Integration ${integration.name} ready (no init)`);
|
|
1219
1464
|
this.flush();
|
|
1220
1465
|
}
|
|
1221
1466
|
});
|
|
@@ -1256,10 +1501,10 @@ class IntegrationManager {
|
|
|
1256
1501
|
if (this.globalQueue.length >= this.config.maxQueueSize) {
|
|
1257
1502
|
// drop oldest
|
|
1258
1503
|
this.globalQueue.shift();
|
|
1259
|
-
this.logger.warn('
|
|
1504
|
+
this.logger.warn('Queue full → dropped oldest');
|
|
1260
1505
|
}
|
|
1261
1506
|
this.globalQueue.push(envelope);
|
|
1262
|
-
this.logger.
|
|
1507
|
+
this.logger.debug(`Queued (${this.globalQueue.length})`, envelope);
|
|
1263
1508
|
return;
|
|
1264
1509
|
}
|
|
1265
1510
|
this.deliver(envelope);
|
|
@@ -1273,8 +1518,17 @@ class IntegrationManager {
|
|
|
1273
1518
|
if (status !== 'ready') continue;
|
|
1274
1519
|
try {
|
|
1275
1520
|
if (evt.type === 'track' && integration.track && evt.name) {
|
|
1521
|
+
this.logger.debug(`Track (${integration.name}) ${evt.name}`, {
|
|
1522
|
+
properties: evt.properties,
|
|
1523
|
+
context: evt.context
|
|
1524
|
+
});
|
|
1276
1525
|
yield integration.track(evt.name, evt.properties, evt.context);
|
|
1277
1526
|
} else if (evt.type === 'identify' && integration.identify) {
|
|
1527
|
+
this.logger.debug(`Identify (${integration.name})`, {
|
|
1528
|
+
userId: evt.context.distinctId,
|
|
1529
|
+
properties: evt.properties,
|
|
1530
|
+
context: evt.context
|
|
1531
|
+
});
|
|
1278
1532
|
yield integration.identify(evt.context.distinctId, evt.properties, evt.context);
|
|
1279
1533
|
}
|
|
1280
1534
|
} catch (e) {
|
|
@@ -1291,7 +1545,7 @@ class IntegrationManager {
|
|
|
1291
1545
|
if (this.globalQueue.length === 0) return;
|
|
1292
1546
|
// If we're not ready don't flush
|
|
1293
1547
|
if (!this.isReady()) return;
|
|
1294
|
-
this.logger.
|
|
1548
|
+
this.logger.debug(`flushing ${this.globalQueue.length} queued events`);
|
|
1295
1549
|
const toSend = this.globalQueue;
|
|
1296
1550
|
this.globalQueue = [];
|
|
1297
1551
|
// deliver all events
|
|
@@ -1303,8 +1557,14 @@ class IntegrationManager {
|
|
|
1303
1557
|
return n;
|
|
1304
1558
|
}
|
|
1305
1559
|
isReady() {
|
|
1560
|
+
const timeElapsed = Date.now() - this.initTime;
|
|
1306
1561
|
// Return if integrations are not ready, or if we haven't waited the max integration wait time
|
|
1307
|
-
if (this.readyCount() < this.integrations.size &&
|
|
1562
|
+
if (this.readyCount() < this.integrations.size && timeElapsed < this.config.maxIntegrationWaitTime) {
|
|
1563
|
+
return false;
|
|
1564
|
+
}
|
|
1565
|
+
if (this.readyCount() < this.integrations.size) {
|
|
1566
|
+
this.logger.info(`proceeding with ${this.readyCount()}/${this.integrations.size} integrations ready after ${timeElapsed}ms wait`);
|
|
1567
|
+
}
|
|
1308
1568
|
return true;
|
|
1309
1569
|
}
|
|
1310
1570
|
/**
|
|
@@ -1326,7 +1586,7 @@ class IntegrationManager {
|
|
|
1326
1586
|
return;
|
|
1327
1587
|
}
|
|
1328
1588
|
this.unloadHandler = () => {
|
|
1329
|
-
this.logger.
|
|
1589
|
+
this.logger.info('page unloading, flushing remaining events');
|
|
1330
1590
|
this.flush();
|
|
1331
1591
|
};
|
|
1332
1592
|
// Use both beforeunload and pagehide for better coverage
|
|
@@ -1345,7 +1605,8 @@ class IntegrationManager {
|
|
|
1345
1605
|
queueLength: this.globalQueue.length,
|
|
1346
1606
|
readyCount: this.readyCount(),
|
|
1347
1607
|
periodicFlushEnabled: this.config.flushInterval > 0,
|
|
1348
|
-
flushInterval: this.config.flushInterval
|
|
1608
|
+
flushInterval: this.config.flushInterval,
|
|
1609
|
+
context: this.context
|
|
1349
1610
|
};
|
|
1350
1611
|
}
|
|
1351
1612
|
}
|
|
@@ -1549,11 +1810,13 @@ class Saasco {
|
|
|
1549
1810
|
this.config = config;
|
|
1550
1811
|
this.lastPageViewPath = '';
|
|
1551
1812
|
this.isInitialized = false;
|
|
1813
|
+
const loggerLevel = getLoggerLevel(this.config);
|
|
1552
1814
|
// Initialize logger
|
|
1553
1815
|
this.logger = new AnalyticsLogger({
|
|
1554
|
-
|
|
1816
|
+
level: loggerLevel,
|
|
1555
1817
|
label: 'Saasco Debug'
|
|
1556
1818
|
});
|
|
1819
|
+
this.logger.info('Saasco started');
|
|
1557
1820
|
if (!config.projectId) {
|
|
1558
1821
|
this.logger.error("Project ID is required but has not been provided. If you are using an env variable make sure it's set correctly.");
|
|
1559
1822
|
return;
|
|
@@ -1568,19 +1831,19 @@ class Saasco {
|
|
|
1568
1831
|
}, this.config.autoPageTracking);
|
|
1569
1832
|
// Initialize integration manager
|
|
1570
1833
|
this.integrationManager = new IntegrationManager({
|
|
1571
|
-
|
|
1834
|
+
loggerLevel,
|
|
1572
1835
|
maxQueueSize: 1000
|
|
1573
1836
|
});
|
|
1574
1837
|
// Set initial context
|
|
1575
1838
|
this.integrationManager.setContext({});
|
|
1576
1839
|
// Initialize integrations immediately (works on both client and server)
|
|
1577
1840
|
this.initIntegrations().catch(error => {
|
|
1578
|
-
this.logger.
|
|
1841
|
+
this.logger.info('Error initializing integrations:', error);
|
|
1579
1842
|
});
|
|
1580
1843
|
}
|
|
1581
1844
|
init() {
|
|
1582
1845
|
if (this.isInitialized) {
|
|
1583
|
-
this.logger.
|
|
1846
|
+
this.logger.info('Saasco is already initialized. Please check your code to ensure that init() is not being called multiple times.');
|
|
1584
1847
|
return;
|
|
1585
1848
|
}
|
|
1586
1849
|
// Export Saasco to the window object for easy access and debugging
|
|
@@ -1589,39 +1852,48 @@ class Saasco {
|
|
|
1589
1852
|
}
|
|
1590
1853
|
// Migrate existing localStorage data to cookies for cross-subdomain support
|
|
1591
1854
|
migrateFromLocalStorage();
|
|
1592
|
-
this.logger.
|
|
1593
|
-
if (this.config.debug) this.logger.
|
|
1594
|
-
if (!this.config.enabled) this.logger.
|
|
1855
|
+
this.logger.info('Saasco initialized', this.config);
|
|
1856
|
+
if (this.config.debug) this.logger.info('Debug mode active. This will log all events to the console.');
|
|
1857
|
+
if (!this.config.enabled) this.logger.info(`Analytics is disabled. No requests will be sent to the server and no integrations will be initialized. ${this.config.debug ? 'Debug mode is active and will still log information.' : ''}`);
|
|
1595
1858
|
this.initAutoPageTracking();
|
|
1596
1859
|
this.isInitialized = true;
|
|
1597
1860
|
}
|
|
1598
1861
|
disableDebug() {
|
|
1599
|
-
this.logger.
|
|
1862
|
+
this.logger.info('Debug mode deactivated.');
|
|
1600
1863
|
this.config.debug = false;
|
|
1601
1864
|
}
|
|
1602
1865
|
enableDebug() {
|
|
1603
1866
|
this.config.debug = true;
|
|
1604
|
-
this.logger.
|
|
1867
|
+
this.logger.info('Debug mode activated.');
|
|
1605
1868
|
}
|
|
1606
1869
|
/**
|
|
1607
1870
|
* Initialize third-party integrations
|
|
1608
1871
|
*/
|
|
1609
1872
|
initIntegrations() {
|
|
1610
1873
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1874
|
+
this.logger.info('Initialize integrations');
|
|
1611
1875
|
if (!this.config.integrations || this.config.integrations.length === 0) return;
|
|
1876
|
+
if (!this.config.enabled) {
|
|
1877
|
+
this.logger.info('Analytics is disabled. Skipping integration initialization.');
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1612
1880
|
for (const integrationConfig of this.config.integrations) {
|
|
1613
1881
|
try {
|
|
1614
1882
|
if (integrationConfig.type === 'facebook-pixel') {
|
|
1615
|
-
this.logger.
|
|
1616
|
-
const fbIntegration = createFacebookPixelIntegration(integrationConfig.config);
|
|
1883
|
+
this.logger.info('Registering Facebook Pixel integration with ID:', integrationConfig.config.pixelId);
|
|
1884
|
+
const fbIntegration = createFacebookPixelIntegration(integrationConfig.config, integrationConfig.debug);
|
|
1617
1885
|
yield this.integrationManager.registerIntegration(fbIntegration);
|
|
1886
|
+
} else if (integrationConfig.type === 'pinterest-tag') {
|
|
1887
|
+
this.logger.info('Registering Pinterest Tag integration with ID:', integrationConfig.config.tagId);
|
|
1888
|
+
const pinterestIntegration = createPinterestTagIntegration(integrationConfig.config, integrationConfig.debug);
|
|
1889
|
+
yield this.integrationManager.registerIntegration(pinterestIntegration);
|
|
1618
1890
|
} else if (integrationConfig.type === 'tiktok-pixel') {
|
|
1619
|
-
this.logger.
|
|
1620
|
-
const tiktokIntegration = createTikTokPixelIntegration(integrationConfig.config);
|
|
1891
|
+
this.logger.info('Registering TikTok Pixel integration with ID:', integrationConfig.config.pixelId);
|
|
1892
|
+
const tiktokIntegration = createTikTokPixelIntegration(integrationConfig.config, integrationConfig.debug);
|
|
1621
1893
|
yield this.integrationManager.registerIntegration(tiktokIntegration);
|
|
1622
1894
|
}
|
|
1623
1895
|
} catch (error) {
|
|
1624
|
-
this.logger.
|
|
1896
|
+
this.logger.info(`Failed to register ${integrationConfig.type} integration:`, error);
|
|
1625
1897
|
}
|
|
1626
1898
|
}
|
|
1627
1899
|
});
|
|
@@ -1674,7 +1946,18 @@ class Saasco {
|
|
|
1674
1946
|
source: isBrowser ? 'client' : 'server',
|
|
1675
1947
|
context: JSON.stringify(context || {})
|
|
1676
1948
|
};
|
|
1677
|
-
|
|
1949
|
+
if (data.action === 'Page View') {
|
|
1950
|
+
this.logger.info('Page View', window.location.href, data);
|
|
1951
|
+
} else {
|
|
1952
|
+
this.logger.info('track', data);
|
|
1953
|
+
}
|
|
1954
|
+
if (!this.config.enabled) {
|
|
1955
|
+
return Promise.resolve({
|
|
1956
|
+
success: true,
|
|
1957
|
+
message: 'Analytics is disabled'
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
// Only send track to integrations if analytics is enabled
|
|
1678
1961
|
this.integrationManager.track(action, properties);
|
|
1679
1962
|
// Send event to API
|
|
1680
1963
|
return this.doRequest('events', data);
|
|
@@ -1719,7 +2002,7 @@ class Saasco {
|
|
|
1719
2002
|
// This should only be called when distinctId is null and there is an existing userId.
|
|
1720
2003
|
// This means the user has logged out and we should reset the session and anonymous IDs
|
|
1721
2004
|
const userIdChangedToNull = distinctId === null && !!getUserId();
|
|
1722
|
-
if (userIdChangedToNull) this.logger.
|
|
2005
|
+
if (userIdChangedToNull) this.logger.info('User logged out');
|
|
1723
2006
|
const reset = userIdChangedToNull;
|
|
1724
2007
|
const sessionId = setSessionId({
|
|
1725
2008
|
reset
|
|
@@ -1730,12 +2013,11 @@ class Saasco {
|
|
|
1730
2013
|
// set the distinct Id to the userId
|
|
1731
2014
|
setUserId(distinctId);
|
|
1732
2015
|
// Update integration manager context and send identify (IntegrationManager will filter by environment)
|
|
1733
|
-
this.integrationManager.setContext({
|
|
2016
|
+
this.integrationManager.setContext(Object.assign({
|
|
1734
2017
|
distinctId,
|
|
1735
2018
|
anonymousId,
|
|
1736
2019
|
sessionId
|
|
1737
|
-
});
|
|
1738
|
-
this.integrationManager.identify(distinctId, properties);
|
|
2020
|
+
}, properties));
|
|
1739
2021
|
// No distinctId provided so we don't track the user
|
|
1740
2022
|
if (!distinctId) return Promise.resolve({
|
|
1741
2023
|
success: true,
|
|
@@ -1752,6 +2034,15 @@ class Saasco {
|
|
|
1752
2034
|
payload: properties || {},
|
|
1753
2035
|
context: context || {}
|
|
1754
2036
|
};
|
|
2037
|
+
this.logger.info('identify', data);
|
|
2038
|
+
// Only send identify to integrations if analytics is enabled
|
|
2039
|
+
if (!this.config.enabled) {
|
|
2040
|
+
return Promise.resolve({
|
|
2041
|
+
success: true,
|
|
2042
|
+
message: 'Analytics is disabled'
|
|
2043
|
+
});
|
|
2044
|
+
}
|
|
2045
|
+
this.integrationManager.identify(distinctId, properties);
|
|
1755
2046
|
return this.doRequest('identify', data);
|
|
1756
2047
|
}
|
|
1757
2048
|
/**
|
|
@@ -1776,11 +2067,6 @@ class Saasco {
|
|
|
1776
2067
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1777
2068
|
const base = this.config.proxy || 'https://www.saasco.com/api/';
|
|
1778
2069
|
const url = `${base}${path}`;
|
|
1779
|
-
if (data.action === 'Page View') {
|
|
1780
|
-
this.logger.log('Page View', window.location.href, data);
|
|
1781
|
-
} else {
|
|
1782
|
-
this.logger.log(data.action || path, data);
|
|
1783
|
-
}
|
|
1784
2070
|
// If analytics is disabled, don't send the request
|
|
1785
2071
|
if (this.config.enabled === false) return {
|
|
1786
2072
|
success: false,
|
|
@@ -1824,11 +2110,11 @@ class Saasco {
|
|
|
1824
2110
|
if (isServer) return console.warn('Saasco auto page tracking is only available in the browser');
|
|
1825
2111
|
// Prevent intitializing auto page tracking more than once
|
|
1826
2112
|
if (window.saascoAutoPageTrackingActive) {
|
|
1827
|
-
this.logger.
|
|
2113
|
+
this.logger.info('Auto Page Tracking already enabled');
|
|
1828
2114
|
return;
|
|
1829
2115
|
}
|
|
1830
2116
|
window.saascoAutoPageTrackingActive = true;
|
|
1831
|
-
this.logger.
|
|
2117
|
+
this.logger.info('Auto Page Tracking enabled');
|
|
1832
2118
|
// Track initial page load
|
|
1833
2119
|
this.page();
|
|
1834
2120
|
// Listen for hash changes if hash tracking is enabled
|
|
@@ -1852,6 +2138,27 @@ class Saasco {
|
|
|
1852
2138
|
return returnValue;
|
|
1853
2139
|
};
|
|
1854
2140
|
}
|
|
2141
|
+
getIntegrationsStats() {
|
|
2142
|
+
return this.integrationManager.getStats();
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
function getLoggerLevel(config) {
|
|
2146
|
+
// Check URL parameters for debug overrides (browser only)
|
|
2147
|
+
let urlDebug = false;
|
|
2148
|
+
let urlDebugVerbose = false;
|
|
2149
|
+
if (!isServer) {
|
|
2150
|
+
try {
|
|
2151
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
2152
|
+
urlDebug = urlParams.get('saasco-debug') === 'true';
|
|
2153
|
+
urlDebugVerbose = urlParams.get('saasco-debug-verbose') === 'true';
|
|
2154
|
+
} catch (error) {
|
|
2155
|
+
// Ignore URL parsing errors
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
// URL parameters override config
|
|
2159
|
+
const effectiveDebug = urlDebug || config.debug;
|
|
2160
|
+
const effectiveDebugVerbose = urlDebugVerbose || config.debugVerbose;
|
|
2161
|
+
return !!effectiveDebugVerbose ? LogLevel.DEBUG : !!effectiveDebug ? LogLevel.INFO : LogLevel.ERROR;
|
|
1855
2162
|
}
|
|
1856
2163
|
|
|
1857
2164
|
const browserContextSchema = zod.z.object({
|
|
@@ -1880,12 +2187,13 @@ const browserContextSchema = zod.z.object({
|
|
|
1880
2187
|
});
|
|
1881
2188
|
|
|
1882
2189
|
exports.IntegrationManager = IntegrationManager;
|
|
1883
|
-
exports.Logger = Logger;
|
|
1884
2190
|
exports.Saasco = Saasco;
|
|
1885
2191
|
exports.browserContextSchema = browserContextSchema;
|
|
1886
2192
|
exports.createFacebookPixelIntegration = createFacebookPixelIntegration;
|
|
2193
|
+
exports.createPinterestTagIntegration = createPinterestTagIntegration;
|
|
1887
2194
|
exports.createTikTokPixelIntegration = createTikTokPixelIntegration;
|
|
1888
2195
|
exports.getBrowserContext = getBrowserContext;
|
|
1889
2196
|
exports.standardFacebookEvents = standardFacebookEvents;
|
|
2197
|
+
exports.standardPinterestEvents = standardPinterestEvents;
|
|
1890
2198
|
exports.standardTikTokEvents = standardTikTokEvents;
|
|
1891
2199
|
exports.timezones = timezones;
|