@hyve-sdk/js 2.11.0 → 2.11.1
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/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +327 -5
- package/dist/index.mjs +327 -5
- package/dist/react.js +327 -5
- package/dist/react.mjs +327 -5
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -33,8 +33,8 @@ interface TelemetryEvent {
|
|
|
33
33
|
event_action: string;
|
|
34
34
|
/** Sub-action for detailed tracking (optional) */
|
|
35
35
|
event_sub_action?: string | null;
|
|
36
|
-
/** Event details as
|
|
37
|
-
event_details?: Record<string,
|
|
36
|
+
/** Event details as object (optional) */
|
|
37
|
+
event_details?: Record<string, unknown> | null;
|
|
38
38
|
/** Mapping details as JSON string or object (optional) */
|
|
39
39
|
mapping_details?: Record<string, any> | string | null;
|
|
40
40
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -33,8 +33,8 @@ interface TelemetryEvent {
|
|
|
33
33
|
event_action: string;
|
|
34
34
|
/** Sub-action for detailed tracking (optional) */
|
|
35
35
|
event_sub_action?: string | null;
|
|
36
|
-
/** Event details as
|
|
37
|
-
event_details?: Record<string,
|
|
36
|
+
/** Event details as object (optional) */
|
|
37
|
+
event_details?: Record<string, unknown> | null;
|
|
38
38
|
/** Mapping details as JSON string or object (optional) */
|
|
39
39
|
mapping_details?: Record<string, any> | string | null;
|
|
40
40
|
}
|
package/dist/index.js
CHANGED
|
@@ -448,6 +448,309 @@ function generateUUID() {
|
|
|
448
448
|
return (0, import_uuid.v4)();
|
|
449
449
|
}
|
|
450
450
|
|
|
451
|
+
// src/utils/device-info.ts
|
|
452
|
+
function detectBrowser(ua) {
|
|
453
|
+
if (/Edg\/(\d+)/.test(ua)) return { name: "Edge", major: RegExp.$1 };
|
|
454
|
+
if (/OPR\/(\d+)/.test(ua)) return { name: "Opera", major: RegExp.$1 };
|
|
455
|
+
if (/Chrome\/(\d+)/.test(ua)) return { name: "Chrome", major: RegExp.$1 };
|
|
456
|
+
if (/Firefox\/(\d+)/.test(ua)) return { name: "Firefox", major: RegExp.$1 };
|
|
457
|
+
if (/Version\/(\d+).*Safari/.test(ua)) return { name: "Safari", major: RegExp.$1 };
|
|
458
|
+
return { name: "unknown", major: "" };
|
|
459
|
+
}
|
|
460
|
+
function detectOS(ua) {
|
|
461
|
+
if (/Windows NT ([\d.]+)/.test(ua)) return { name: "Windows", version: RegExp.$1 };
|
|
462
|
+
if (/Mac OS X ([\d_]+)/.test(ua)) return { name: "macOS", version: RegExp.$1.replace(/_/g, ".") };
|
|
463
|
+
if (/Android ([\d.]+)/.test(ua)) return { name: "Android", version: RegExp.$1 };
|
|
464
|
+
if (/iPhone OS ([\d_]+)/.test(ua)) return { name: "iOS", version: RegExp.$1.replace(/_/g, ".") };
|
|
465
|
+
if (/iPad.*OS ([\d_]+)/.test(ua)) return { name: "iOS", version: RegExp.$1.replace(/_/g, ".") };
|
|
466
|
+
if (/CrOS/.test(ua)) return { name: "Chrome OS", version: "" };
|
|
467
|
+
if (/Linux/.test(ua)) return { name: "Linux", version: "" };
|
|
468
|
+
return { name: "unknown", version: "" };
|
|
469
|
+
}
|
|
470
|
+
function detectDeviceType(ua) {
|
|
471
|
+
if (/Mobi|Android(?!.*Tablet)|iPhone|iPod/i.test(ua)) return "mobile";
|
|
472
|
+
if (/Tablet|iPad|Android.*Tablet/i.test(ua)) return "tablet";
|
|
473
|
+
return "desktop";
|
|
474
|
+
}
|
|
475
|
+
var _cache = null;
|
|
476
|
+
function getEssentialDeviceInfo() {
|
|
477
|
+
if (_cache) return _cache;
|
|
478
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") {
|
|
479
|
+
return {
|
|
480
|
+
browser: "unknown",
|
|
481
|
+
os: "unknown",
|
|
482
|
+
device_type: null,
|
|
483
|
+
viewport: "0x0",
|
|
484
|
+
screen: "0x0",
|
|
485
|
+
pixel_ratio: null,
|
|
486
|
+
language: null,
|
|
487
|
+
timezone: null,
|
|
488
|
+
country_code: null
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
const ua = navigator.userAgent;
|
|
492
|
+
const browser = detectBrowser(ua);
|
|
493
|
+
const os = detectOS(ua);
|
|
494
|
+
const deviceType = detectDeviceType(ua);
|
|
495
|
+
let timezone = null;
|
|
496
|
+
try {
|
|
497
|
+
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
498
|
+
} catch {
|
|
499
|
+
}
|
|
500
|
+
const language = navigator.language || null;
|
|
501
|
+
let country_code = null;
|
|
502
|
+
if (language) {
|
|
503
|
+
const parts = language.split("-");
|
|
504
|
+
if (parts.length > 1) {
|
|
505
|
+
country_code = parts[parts.length - 1].toUpperCase();
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
_cache = {
|
|
509
|
+
browser: browser.major ? `${browser.name} ${browser.major}` : browser.name,
|
|
510
|
+
os: os.version ? `${os.name} ${os.version}` : os.name,
|
|
511
|
+
device_type: deviceType,
|
|
512
|
+
viewport: `${window.innerWidth ?? 0}x${window.innerHeight ?? 0}`,
|
|
513
|
+
screen: `${window.screen?.width ?? 0}x${window.screen?.height ?? 0}`,
|
|
514
|
+
pixel_ratio: window.devicePixelRatio || null,
|
|
515
|
+
language,
|
|
516
|
+
timezone,
|
|
517
|
+
country_code
|
|
518
|
+
};
|
|
519
|
+
return _cache;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// src/utils/attribution.ts
|
|
523
|
+
var EMBEDDING_PLATFORM_PATTERNS = {
|
|
524
|
+
twitter: [/t\.co/i, /twitter\.com/i, /x\.com/i, /mobile\.twitter\.com/i, /mobile\.x\.com/i],
|
|
525
|
+
discord: [/discord\.com/i, /discordapp\.com/i, /discord\.gg/i],
|
|
526
|
+
telegram: [/telegram\.org/i, /telegram\.me/i, /t\.me/i, /web\.telegram\.org/i],
|
|
527
|
+
facebook: [/facebook\.com/i, /fb\.com/i, /m\.facebook\.com/i, /mobile\.facebook\.com/i, /meta\.com/i],
|
|
528
|
+
reddit: [/reddit\.com/i, /redd\.it/i, /old\.reddit\.com/i, /www\.reddit\.com/i],
|
|
529
|
+
linkedin: [/linkedin\.com/i, /lnkd\.in/i],
|
|
530
|
+
instagram: [/instagram\.com/i, /instagr\.am/i],
|
|
531
|
+
youtube: [/youtube\.com/i, /youtu\.be/i, /m\.youtube\.com/i],
|
|
532
|
+
twitch: [/twitch\.tv/i, /m\.twitch\.tv/i],
|
|
533
|
+
farcaster: [/warpcast\.com/i, /farcaster\.xyz/i, /miniapps\.farcaster\.xyz/i],
|
|
534
|
+
worldapp: [/world\.app/i, /worldcoin\.org/i],
|
|
535
|
+
tiktok: [/tiktok\.com/i, /vm\.tiktok\.com/i]
|
|
536
|
+
};
|
|
537
|
+
var AttributionManager = class _AttributionManager {
|
|
538
|
+
static instance;
|
|
539
|
+
cachedData = null;
|
|
540
|
+
STORAGE_KEY = "hyve_attribution";
|
|
541
|
+
SESSION_COUNT_KEY = "hyve_session_count";
|
|
542
|
+
static getInstance() {
|
|
543
|
+
if (!_AttributionManager.instance) {
|
|
544
|
+
_AttributionManager.instance = new _AttributionManager();
|
|
545
|
+
}
|
|
546
|
+
return _AttributionManager.instance;
|
|
547
|
+
}
|
|
548
|
+
captureAttribution() {
|
|
549
|
+
if (typeof window === "undefined") return this.getEmptyAttribution();
|
|
550
|
+
if (this.cachedData) return this.cachedData;
|
|
551
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
552
|
+
const referrerUrl = document.referrer;
|
|
553
|
+
const referrerDomain = this.extractDomain(referrerUrl);
|
|
554
|
+
const platformDetection = this.detectEmbeddingPlatform(urlParams, referrerUrl);
|
|
555
|
+
const attribution = {
|
|
556
|
+
utm_source: urlParams.get("utm_source"),
|
|
557
|
+
utm_medium: urlParams.get("utm_medium"),
|
|
558
|
+
utm_campaign: urlParams.get("utm_campaign"),
|
|
559
|
+
utm_term: urlParams.get("utm_term"),
|
|
560
|
+
utm_content: urlParams.get("utm_content"),
|
|
561
|
+
utm_id: urlParams.get("utm_id"),
|
|
562
|
+
utm_source_platform: urlParams.get("utm_source_platform"),
|
|
563
|
+
platform_id: platformDetection.platform,
|
|
564
|
+
is_embedded: platformDetection.isEmbedded,
|
|
565
|
+
referrer_url: referrerUrl || null,
|
|
566
|
+
referrer_domain: referrerDomain,
|
|
567
|
+
referrer_source: this.categorizeReferrer(referrerUrl),
|
|
568
|
+
is_first_party_referrer: this.isFirstPartyReferrer(referrerDomain),
|
|
569
|
+
traffic_type: this.classifyTrafficType(urlParams, referrerUrl),
|
|
570
|
+
first_visit_timestamp: Date.now(),
|
|
571
|
+
session_count: this.getSessionCount() + 1,
|
|
572
|
+
is_bot: this.detectBot(),
|
|
573
|
+
attribution_confidence: this.calculateConfidence(urlParams, referrerUrl)
|
|
574
|
+
};
|
|
575
|
+
this.cachedData = attribution;
|
|
576
|
+
this.storeAttribution(attribution);
|
|
577
|
+
return attribution;
|
|
578
|
+
}
|
|
579
|
+
getAttribution() {
|
|
580
|
+
if (this.cachedData) return this.cachedData;
|
|
581
|
+
if (typeof window === "undefined") return this.getEmptyAttribution();
|
|
582
|
+
const stored = sessionStorage.getItem(this.STORAGE_KEY);
|
|
583
|
+
if (stored) {
|
|
584
|
+
try {
|
|
585
|
+
const parsed = JSON.parse(stored);
|
|
586
|
+
if (this.isValidAttributionData(parsed)) {
|
|
587
|
+
this.cachedData = parsed;
|
|
588
|
+
return parsed;
|
|
589
|
+
}
|
|
590
|
+
} catch {
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return this.captureAttribution();
|
|
594
|
+
}
|
|
595
|
+
classifyTrafficType(urlParams, referrerUrl) {
|
|
596
|
+
if (urlParams.get("utm_source")) return "campaign";
|
|
597
|
+
if (!referrerUrl) return "direct";
|
|
598
|
+
const domain = this.extractDomain(referrerUrl);
|
|
599
|
+
if (this.isSearchEngine(domain)) return "search";
|
|
600
|
+
if (this.isSocialPlatform(domain)) return "social";
|
|
601
|
+
if (this.isEmailClient(domain)) return "email";
|
|
602
|
+
if (this.isFirstPartyReferrer(domain)) return "direct";
|
|
603
|
+
return "referral";
|
|
604
|
+
}
|
|
605
|
+
isCdnUrl(url) {
|
|
606
|
+
if (!url) return false;
|
|
607
|
+
return [/cloudfront\.net/i, /cdn\.[\w-]+\.com/i, /\.cdn\./i, /fastly\.net/i, /akamai/i, /\.cloudflare\./i].some(
|
|
608
|
+
(p) => p.test(url)
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
detectEmbeddingPlatform(urlParams, referrerUrl) {
|
|
612
|
+
let isEmbedded = false;
|
|
613
|
+
try {
|
|
614
|
+
isEmbedded = window.self !== window.top;
|
|
615
|
+
} catch {
|
|
616
|
+
isEmbedded = true;
|
|
617
|
+
}
|
|
618
|
+
if (!isEmbedded) return { platform: "web", isEmbedded: false };
|
|
619
|
+
const platformParam = urlParams.get("platform")?.toLowerCase().trim();
|
|
620
|
+
if (platformParam && /^[a-z0-9_-]+$/.test(platformParam)) {
|
|
621
|
+
return { platform: platformParam, isEmbedded: true };
|
|
622
|
+
}
|
|
623
|
+
if (!referrerUrl || this.isCdnUrl(referrerUrl)) {
|
|
624
|
+
return { platform: "unknown", isEmbedded: true };
|
|
625
|
+
}
|
|
626
|
+
const normalizedRef = referrerUrl.toLowerCase();
|
|
627
|
+
for (const [platform, patterns] of Object.entries(EMBEDDING_PLATFORM_PATTERNS)) {
|
|
628
|
+
if (patterns.some((p) => p.test(normalizedRef))) {
|
|
629
|
+
return { platform, isEmbedded: true };
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
try {
|
|
633
|
+
if (window.location.ancestorOrigins?.length > 0) {
|
|
634
|
+
const parentOrigin = window.location.ancestorOrigins[0];
|
|
635
|
+
if (parentOrigin && !this.isCdnUrl(parentOrigin)) {
|
|
636
|
+
for (const [platform, patterns] of Object.entries(EMBEDDING_PLATFORM_PATTERNS)) {
|
|
637
|
+
if (patterns.some((p) => p.test(parentOrigin))) {
|
|
638
|
+
return { platform, isEmbedded: true };
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
} catch {
|
|
644
|
+
}
|
|
645
|
+
return { platform: "unknown", isEmbedded: true };
|
|
646
|
+
}
|
|
647
|
+
categorizeReferrer(referrerUrl) {
|
|
648
|
+
if (!referrerUrl) return "direct";
|
|
649
|
+
const r = referrerUrl.toLowerCase();
|
|
650
|
+
if (r.includes("checkout.stripe.com")) return "direct";
|
|
651
|
+
if (r.includes("t.co") || r.includes("x.com") || r.includes("twitter.com")) return "twitter";
|
|
652
|
+
if (r.includes("farcaster.xyz") || r.includes("warpcast.com")) return "farcaster";
|
|
653
|
+
if (r.includes("discord.com") || r.includes("discord.gg")) return "discord";
|
|
654
|
+
if (r.includes("t.me") || r.includes("telegram.me") || r.includes("telegram.org")) return "telegram";
|
|
655
|
+
if (r.includes("reddit.com") || r.includes("old.reddit.com")) return "reddit";
|
|
656
|
+
if (r.includes("facebook.com") || r.includes("fb.com") || r.includes("meta.com")) return "facebook";
|
|
657
|
+
if (r.includes("linkedin.com")) return "linkedin";
|
|
658
|
+
if (r.includes("youtube.com") || r.includes("youtu.be")) return "youtube";
|
|
659
|
+
if (r.includes("google.com")) return "google";
|
|
660
|
+
if (r.includes("bing.com")) return "bing";
|
|
661
|
+
if (r.includes("duckduckgo.com")) return "duckduckgo";
|
|
662
|
+
if (r.includes("yahoo.com")) return "yahoo";
|
|
663
|
+
if (r.includes("world.app")) return "worldapp";
|
|
664
|
+
if (r.includes("instagram.com")) return "instagram";
|
|
665
|
+
if (r.includes("tiktok.com")) return "tiktok";
|
|
666
|
+
return this.extractDomain(referrerUrl) || "unknown";
|
|
667
|
+
}
|
|
668
|
+
detectBot() {
|
|
669
|
+
if (typeof navigator === "undefined") return false;
|
|
670
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
671
|
+
return ["bot", "crawler", "spider", "scraper", "headless", "phantom", "selenium", "puppeteer", "playwright", "googlebot", "bingbot", "slurp", "duckduckbot"].some(
|
|
672
|
+
(indicator) => ua.includes(indicator)
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
calculateConfidence(urlParams, referrerUrl) {
|
|
676
|
+
let confidence = 0.5;
|
|
677
|
+
if (urlParams.get("utm_source")) confidence += 0.3;
|
|
678
|
+
if (urlParams.get("utm_campaign")) confidence += 0.2;
|
|
679
|
+
if (urlParams.get("utm_medium")) confidence += 0.1;
|
|
680
|
+
if (referrerUrl && !this.isFirstPartyReferrer(this.extractDomain(referrerUrl))) confidence += 0.2;
|
|
681
|
+
if (this.detectBot()) confidence -= 0.5;
|
|
682
|
+
if (urlParams.get("utm_source") === "test" || urlParams.get("utm_campaign") === "test") confidence -= 0.2;
|
|
683
|
+
return Math.max(0, Math.min(1, confidence));
|
|
684
|
+
}
|
|
685
|
+
extractDomain(url) {
|
|
686
|
+
if (!url) return "";
|
|
687
|
+
try {
|
|
688
|
+
return new URL(url).hostname.toLowerCase();
|
|
689
|
+
} catch {
|
|
690
|
+
return "";
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
isFirstPartyReferrer(domain) {
|
|
694
|
+
return ["hyve.gg", "dev.hyve.gg", "localhost"].some((d) => domain.includes(d));
|
|
695
|
+
}
|
|
696
|
+
isSearchEngine(domain) {
|
|
697
|
+
return ["google.com", "bing.com", "duckduckgo.com", "yahoo.com", "yandex.com"].some((e) => domain.includes(e));
|
|
698
|
+
}
|
|
699
|
+
isSocialPlatform(domain) {
|
|
700
|
+
return ["twitter.com", "x.com", "facebook.com", "meta.com", "linkedin.com", "reddit.com", "instagram.com", "tiktok.com", "youtube.com", "discord.com", "telegram.org", "farcaster.xyz", "warpcast.com", "t.me", "world.app"].some(
|
|
701
|
+
(p) => domain.includes(p)
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
isEmailClient(domain) {
|
|
705
|
+
return ["mail.google.com", "outlook.live.com", "mail.yahoo.com", "mail.aol.com"].some((c) => domain.includes(c));
|
|
706
|
+
}
|
|
707
|
+
getSessionCount() {
|
|
708
|
+
if (typeof window === "undefined") return 0;
|
|
709
|
+
try {
|
|
710
|
+
const stored = localStorage.getItem(this.SESSION_COUNT_KEY);
|
|
711
|
+
return stored ? parseInt(stored, 10) : 0;
|
|
712
|
+
} catch {
|
|
713
|
+
return 0;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
storeAttribution(attribution) {
|
|
717
|
+
if (typeof window === "undefined") return;
|
|
718
|
+
try {
|
|
719
|
+
sessionStorage.setItem(this.STORAGE_KEY, JSON.stringify(attribution));
|
|
720
|
+
localStorage.setItem(this.SESSION_COUNT_KEY, attribution.session_count.toString());
|
|
721
|
+
} catch {
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
isValidAttributionData(data) {
|
|
725
|
+
return data !== null && typeof data === "object" && "traffic_type" in data && "attribution_confidence" in data && "platform_id" in data && "is_embedded" in data;
|
|
726
|
+
}
|
|
727
|
+
getEmptyAttribution() {
|
|
728
|
+
return {
|
|
729
|
+
utm_source: null,
|
|
730
|
+
utm_medium: null,
|
|
731
|
+
utm_campaign: null,
|
|
732
|
+
utm_term: null,
|
|
733
|
+
utm_content: null,
|
|
734
|
+
utm_id: null,
|
|
735
|
+
utm_source_platform: null,
|
|
736
|
+
platform_id: "web",
|
|
737
|
+
is_embedded: false,
|
|
738
|
+
referrer_url: null,
|
|
739
|
+
referrer_domain: null,
|
|
740
|
+
referrer_source: null,
|
|
741
|
+
is_first_party_referrer: false,
|
|
742
|
+
traffic_type: "direct",
|
|
743
|
+
first_visit_timestamp: 0,
|
|
744
|
+
session_count: 0,
|
|
745
|
+
is_bot: false,
|
|
746
|
+
attribution_confidence: 0
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
};
|
|
750
|
+
function getAttributionData() {
|
|
751
|
+
return AttributionManager.getInstance().getAttribution();
|
|
752
|
+
}
|
|
753
|
+
|
|
451
754
|
// src/services/ads.ts
|
|
452
755
|
var AdsService = class {
|
|
453
756
|
config = {
|
|
@@ -1758,20 +2061,39 @@ var HyveClient = class {
|
|
|
1758
2061
|
return false;
|
|
1759
2062
|
}
|
|
1760
2063
|
}
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
2064
|
+
let parsedEventDetails = {};
|
|
2065
|
+
if (eventDetails) {
|
|
2066
|
+
if (typeof eventDetails === "string") {
|
|
2067
|
+
try {
|
|
2068
|
+
parsedEventDetails = JSON.parse(eventDetails);
|
|
2069
|
+
} catch {
|
|
2070
|
+
}
|
|
2071
|
+
} else {
|
|
2072
|
+
parsedEventDetails = eventDetails;
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
const attribution = getAttributionData();
|
|
2076
|
+
const enrichedEventDetails = {
|
|
2077
|
+
// Device info
|
|
2078
|
+
...getEssentialDeviceInfo(),
|
|
2079
|
+
// Attribution data
|
|
2080
|
+
...attribution,
|
|
2081
|
+
// Timestamp and session context
|
|
2082
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2083
|
+
session_id: this.sessionId,
|
|
2084
|
+
// Event-specific details can override any of the above
|
|
2085
|
+
...parsedEventDetails
|
|
1764
2086
|
};
|
|
1765
2087
|
const telemetryEvent = {
|
|
1766
2088
|
game_id: this.gameId,
|
|
1767
2089
|
session_id: this.sessionId,
|
|
1768
|
-
platform_id: platformId || null,
|
|
2090
|
+
platform_id: platformId || attribution.platform_id || null,
|
|
1769
2091
|
event_location: eventLocation,
|
|
1770
2092
|
event_category: eventCategory,
|
|
1771
2093
|
event_action: eventAction,
|
|
1772
2094
|
event_sub_category: eventSubCategory || null,
|
|
1773
2095
|
event_sub_action: eventSubAction || null,
|
|
1774
|
-
event_details:
|
|
2096
|
+
event_details: enrichedEventDetails
|
|
1775
2097
|
};
|
|
1776
2098
|
logger.debug("Sending telemetry event:", telemetryEvent);
|
|
1777
2099
|
const telemetryUrl = `${this.apiBaseUrl}/api/v1/analytics/send`;
|