@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/react.js
CHANGED
|
@@ -409,6 +409,309 @@ function generateUUID() {
|
|
|
409
409
|
return (0, import_uuid.v4)();
|
|
410
410
|
}
|
|
411
411
|
|
|
412
|
+
// src/utils/device-info.ts
|
|
413
|
+
function detectBrowser(ua) {
|
|
414
|
+
if (/Edg\/(\d+)/.test(ua)) return { name: "Edge", major: RegExp.$1 };
|
|
415
|
+
if (/OPR\/(\d+)/.test(ua)) return { name: "Opera", major: RegExp.$1 };
|
|
416
|
+
if (/Chrome\/(\d+)/.test(ua)) return { name: "Chrome", major: RegExp.$1 };
|
|
417
|
+
if (/Firefox\/(\d+)/.test(ua)) return { name: "Firefox", major: RegExp.$1 };
|
|
418
|
+
if (/Version\/(\d+).*Safari/.test(ua)) return { name: "Safari", major: RegExp.$1 };
|
|
419
|
+
return { name: "unknown", major: "" };
|
|
420
|
+
}
|
|
421
|
+
function detectOS(ua) {
|
|
422
|
+
if (/Windows NT ([\d.]+)/.test(ua)) return { name: "Windows", version: RegExp.$1 };
|
|
423
|
+
if (/Mac OS X ([\d_]+)/.test(ua)) return { name: "macOS", version: RegExp.$1.replace(/_/g, ".") };
|
|
424
|
+
if (/Android ([\d.]+)/.test(ua)) return { name: "Android", version: RegExp.$1 };
|
|
425
|
+
if (/iPhone OS ([\d_]+)/.test(ua)) return { name: "iOS", version: RegExp.$1.replace(/_/g, ".") };
|
|
426
|
+
if (/iPad.*OS ([\d_]+)/.test(ua)) return { name: "iOS", version: RegExp.$1.replace(/_/g, ".") };
|
|
427
|
+
if (/CrOS/.test(ua)) return { name: "Chrome OS", version: "" };
|
|
428
|
+
if (/Linux/.test(ua)) return { name: "Linux", version: "" };
|
|
429
|
+
return { name: "unknown", version: "" };
|
|
430
|
+
}
|
|
431
|
+
function detectDeviceType(ua) {
|
|
432
|
+
if (/Mobi|Android(?!.*Tablet)|iPhone|iPod/i.test(ua)) return "mobile";
|
|
433
|
+
if (/Tablet|iPad|Android.*Tablet/i.test(ua)) return "tablet";
|
|
434
|
+
return "desktop";
|
|
435
|
+
}
|
|
436
|
+
var _cache = null;
|
|
437
|
+
function getEssentialDeviceInfo() {
|
|
438
|
+
if (_cache) return _cache;
|
|
439
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") {
|
|
440
|
+
return {
|
|
441
|
+
browser: "unknown",
|
|
442
|
+
os: "unknown",
|
|
443
|
+
device_type: null,
|
|
444
|
+
viewport: "0x0",
|
|
445
|
+
screen: "0x0",
|
|
446
|
+
pixel_ratio: null,
|
|
447
|
+
language: null,
|
|
448
|
+
timezone: null,
|
|
449
|
+
country_code: null
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
const ua = navigator.userAgent;
|
|
453
|
+
const browser = detectBrowser(ua);
|
|
454
|
+
const os = detectOS(ua);
|
|
455
|
+
const deviceType = detectDeviceType(ua);
|
|
456
|
+
let timezone = null;
|
|
457
|
+
try {
|
|
458
|
+
timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
459
|
+
} catch {
|
|
460
|
+
}
|
|
461
|
+
const language = navigator.language || null;
|
|
462
|
+
let country_code = null;
|
|
463
|
+
if (language) {
|
|
464
|
+
const parts = language.split("-");
|
|
465
|
+
if (parts.length > 1) {
|
|
466
|
+
country_code = parts[parts.length - 1].toUpperCase();
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
_cache = {
|
|
470
|
+
browser: browser.major ? `${browser.name} ${browser.major}` : browser.name,
|
|
471
|
+
os: os.version ? `${os.name} ${os.version}` : os.name,
|
|
472
|
+
device_type: deviceType,
|
|
473
|
+
viewport: `${window.innerWidth ?? 0}x${window.innerHeight ?? 0}`,
|
|
474
|
+
screen: `${window.screen?.width ?? 0}x${window.screen?.height ?? 0}`,
|
|
475
|
+
pixel_ratio: window.devicePixelRatio || null,
|
|
476
|
+
language,
|
|
477
|
+
timezone,
|
|
478
|
+
country_code
|
|
479
|
+
};
|
|
480
|
+
return _cache;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/utils/attribution.ts
|
|
484
|
+
var EMBEDDING_PLATFORM_PATTERNS = {
|
|
485
|
+
twitter: [/t\.co/i, /twitter\.com/i, /x\.com/i, /mobile\.twitter\.com/i, /mobile\.x\.com/i],
|
|
486
|
+
discord: [/discord\.com/i, /discordapp\.com/i, /discord\.gg/i],
|
|
487
|
+
telegram: [/telegram\.org/i, /telegram\.me/i, /t\.me/i, /web\.telegram\.org/i],
|
|
488
|
+
facebook: [/facebook\.com/i, /fb\.com/i, /m\.facebook\.com/i, /mobile\.facebook\.com/i, /meta\.com/i],
|
|
489
|
+
reddit: [/reddit\.com/i, /redd\.it/i, /old\.reddit\.com/i, /www\.reddit\.com/i],
|
|
490
|
+
linkedin: [/linkedin\.com/i, /lnkd\.in/i],
|
|
491
|
+
instagram: [/instagram\.com/i, /instagr\.am/i],
|
|
492
|
+
youtube: [/youtube\.com/i, /youtu\.be/i, /m\.youtube\.com/i],
|
|
493
|
+
twitch: [/twitch\.tv/i, /m\.twitch\.tv/i],
|
|
494
|
+
farcaster: [/warpcast\.com/i, /farcaster\.xyz/i, /miniapps\.farcaster\.xyz/i],
|
|
495
|
+
worldapp: [/world\.app/i, /worldcoin\.org/i],
|
|
496
|
+
tiktok: [/tiktok\.com/i, /vm\.tiktok\.com/i]
|
|
497
|
+
};
|
|
498
|
+
var AttributionManager = class _AttributionManager {
|
|
499
|
+
static instance;
|
|
500
|
+
cachedData = null;
|
|
501
|
+
STORAGE_KEY = "hyve_attribution";
|
|
502
|
+
SESSION_COUNT_KEY = "hyve_session_count";
|
|
503
|
+
static getInstance() {
|
|
504
|
+
if (!_AttributionManager.instance) {
|
|
505
|
+
_AttributionManager.instance = new _AttributionManager();
|
|
506
|
+
}
|
|
507
|
+
return _AttributionManager.instance;
|
|
508
|
+
}
|
|
509
|
+
captureAttribution() {
|
|
510
|
+
if (typeof window === "undefined") return this.getEmptyAttribution();
|
|
511
|
+
if (this.cachedData) return this.cachedData;
|
|
512
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
513
|
+
const referrerUrl = document.referrer;
|
|
514
|
+
const referrerDomain = this.extractDomain(referrerUrl);
|
|
515
|
+
const platformDetection = this.detectEmbeddingPlatform(urlParams, referrerUrl);
|
|
516
|
+
const attribution = {
|
|
517
|
+
utm_source: urlParams.get("utm_source"),
|
|
518
|
+
utm_medium: urlParams.get("utm_medium"),
|
|
519
|
+
utm_campaign: urlParams.get("utm_campaign"),
|
|
520
|
+
utm_term: urlParams.get("utm_term"),
|
|
521
|
+
utm_content: urlParams.get("utm_content"),
|
|
522
|
+
utm_id: urlParams.get("utm_id"),
|
|
523
|
+
utm_source_platform: urlParams.get("utm_source_platform"),
|
|
524
|
+
platform_id: platformDetection.platform,
|
|
525
|
+
is_embedded: platformDetection.isEmbedded,
|
|
526
|
+
referrer_url: referrerUrl || null,
|
|
527
|
+
referrer_domain: referrerDomain,
|
|
528
|
+
referrer_source: this.categorizeReferrer(referrerUrl),
|
|
529
|
+
is_first_party_referrer: this.isFirstPartyReferrer(referrerDomain),
|
|
530
|
+
traffic_type: this.classifyTrafficType(urlParams, referrerUrl),
|
|
531
|
+
first_visit_timestamp: Date.now(),
|
|
532
|
+
session_count: this.getSessionCount() + 1,
|
|
533
|
+
is_bot: this.detectBot(),
|
|
534
|
+
attribution_confidence: this.calculateConfidence(urlParams, referrerUrl)
|
|
535
|
+
};
|
|
536
|
+
this.cachedData = attribution;
|
|
537
|
+
this.storeAttribution(attribution);
|
|
538
|
+
return attribution;
|
|
539
|
+
}
|
|
540
|
+
getAttribution() {
|
|
541
|
+
if (this.cachedData) return this.cachedData;
|
|
542
|
+
if (typeof window === "undefined") return this.getEmptyAttribution();
|
|
543
|
+
const stored = sessionStorage.getItem(this.STORAGE_KEY);
|
|
544
|
+
if (stored) {
|
|
545
|
+
try {
|
|
546
|
+
const parsed = JSON.parse(stored);
|
|
547
|
+
if (this.isValidAttributionData(parsed)) {
|
|
548
|
+
this.cachedData = parsed;
|
|
549
|
+
return parsed;
|
|
550
|
+
}
|
|
551
|
+
} catch {
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return this.captureAttribution();
|
|
555
|
+
}
|
|
556
|
+
classifyTrafficType(urlParams, referrerUrl) {
|
|
557
|
+
if (urlParams.get("utm_source")) return "campaign";
|
|
558
|
+
if (!referrerUrl) return "direct";
|
|
559
|
+
const domain = this.extractDomain(referrerUrl);
|
|
560
|
+
if (this.isSearchEngine(domain)) return "search";
|
|
561
|
+
if (this.isSocialPlatform(domain)) return "social";
|
|
562
|
+
if (this.isEmailClient(domain)) return "email";
|
|
563
|
+
if (this.isFirstPartyReferrer(domain)) return "direct";
|
|
564
|
+
return "referral";
|
|
565
|
+
}
|
|
566
|
+
isCdnUrl(url) {
|
|
567
|
+
if (!url) return false;
|
|
568
|
+
return [/cloudfront\.net/i, /cdn\.[\w-]+\.com/i, /\.cdn\./i, /fastly\.net/i, /akamai/i, /\.cloudflare\./i].some(
|
|
569
|
+
(p) => p.test(url)
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
detectEmbeddingPlatform(urlParams, referrerUrl) {
|
|
573
|
+
let isEmbedded = false;
|
|
574
|
+
try {
|
|
575
|
+
isEmbedded = window.self !== window.top;
|
|
576
|
+
} catch {
|
|
577
|
+
isEmbedded = true;
|
|
578
|
+
}
|
|
579
|
+
if (!isEmbedded) return { platform: "web", isEmbedded: false };
|
|
580
|
+
const platformParam = urlParams.get("platform")?.toLowerCase().trim();
|
|
581
|
+
if (platformParam && /^[a-z0-9_-]+$/.test(platformParam)) {
|
|
582
|
+
return { platform: platformParam, isEmbedded: true };
|
|
583
|
+
}
|
|
584
|
+
if (!referrerUrl || this.isCdnUrl(referrerUrl)) {
|
|
585
|
+
return { platform: "unknown", isEmbedded: true };
|
|
586
|
+
}
|
|
587
|
+
const normalizedRef = referrerUrl.toLowerCase();
|
|
588
|
+
for (const [platform, patterns] of Object.entries(EMBEDDING_PLATFORM_PATTERNS)) {
|
|
589
|
+
if (patterns.some((p) => p.test(normalizedRef))) {
|
|
590
|
+
return { platform, isEmbedded: true };
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
if (window.location.ancestorOrigins?.length > 0) {
|
|
595
|
+
const parentOrigin = window.location.ancestorOrigins[0];
|
|
596
|
+
if (parentOrigin && !this.isCdnUrl(parentOrigin)) {
|
|
597
|
+
for (const [platform, patterns] of Object.entries(EMBEDDING_PLATFORM_PATTERNS)) {
|
|
598
|
+
if (patterns.some((p) => p.test(parentOrigin))) {
|
|
599
|
+
return { platform, isEmbedded: true };
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
} catch {
|
|
605
|
+
}
|
|
606
|
+
return { platform: "unknown", isEmbedded: true };
|
|
607
|
+
}
|
|
608
|
+
categorizeReferrer(referrerUrl) {
|
|
609
|
+
if (!referrerUrl) return "direct";
|
|
610
|
+
const r = referrerUrl.toLowerCase();
|
|
611
|
+
if (r.includes("checkout.stripe.com")) return "direct";
|
|
612
|
+
if (r.includes("t.co") || r.includes("x.com") || r.includes("twitter.com")) return "twitter";
|
|
613
|
+
if (r.includes("farcaster.xyz") || r.includes("warpcast.com")) return "farcaster";
|
|
614
|
+
if (r.includes("discord.com") || r.includes("discord.gg")) return "discord";
|
|
615
|
+
if (r.includes("t.me") || r.includes("telegram.me") || r.includes("telegram.org")) return "telegram";
|
|
616
|
+
if (r.includes("reddit.com") || r.includes("old.reddit.com")) return "reddit";
|
|
617
|
+
if (r.includes("facebook.com") || r.includes("fb.com") || r.includes("meta.com")) return "facebook";
|
|
618
|
+
if (r.includes("linkedin.com")) return "linkedin";
|
|
619
|
+
if (r.includes("youtube.com") || r.includes("youtu.be")) return "youtube";
|
|
620
|
+
if (r.includes("google.com")) return "google";
|
|
621
|
+
if (r.includes("bing.com")) return "bing";
|
|
622
|
+
if (r.includes("duckduckgo.com")) return "duckduckgo";
|
|
623
|
+
if (r.includes("yahoo.com")) return "yahoo";
|
|
624
|
+
if (r.includes("world.app")) return "worldapp";
|
|
625
|
+
if (r.includes("instagram.com")) return "instagram";
|
|
626
|
+
if (r.includes("tiktok.com")) return "tiktok";
|
|
627
|
+
return this.extractDomain(referrerUrl) || "unknown";
|
|
628
|
+
}
|
|
629
|
+
detectBot() {
|
|
630
|
+
if (typeof navigator === "undefined") return false;
|
|
631
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
632
|
+
return ["bot", "crawler", "spider", "scraper", "headless", "phantom", "selenium", "puppeteer", "playwright", "googlebot", "bingbot", "slurp", "duckduckbot"].some(
|
|
633
|
+
(indicator) => ua.includes(indicator)
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
calculateConfidence(urlParams, referrerUrl) {
|
|
637
|
+
let confidence = 0.5;
|
|
638
|
+
if (urlParams.get("utm_source")) confidence += 0.3;
|
|
639
|
+
if (urlParams.get("utm_campaign")) confidence += 0.2;
|
|
640
|
+
if (urlParams.get("utm_medium")) confidence += 0.1;
|
|
641
|
+
if (referrerUrl && !this.isFirstPartyReferrer(this.extractDomain(referrerUrl))) confidence += 0.2;
|
|
642
|
+
if (this.detectBot()) confidence -= 0.5;
|
|
643
|
+
if (urlParams.get("utm_source") === "test" || urlParams.get("utm_campaign") === "test") confidence -= 0.2;
|
|
644
|
+
return Math.max(0, Math.min(1, confidence));
|
|
645
|
+
}
|
|
646
|
+
extractDomain(url) {
|
|
647
|
+
if (!url) return "";
|
|
648
|
+
try {
|
|
649
|
+
return new URL(url).hostname.toLowerCase();
|
|
650
|
+
} catch {
|
|
651
|
+
return "";
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
isFirstPartyReferrer(domain) {
|
|
655
|
+
return ["hyve.gg", "dev.hyve.gg", "localhost"].some((d) => domain.includes(d));
|
|
656
|
+
}
|
|
657
|
+
isSearchEngine(domain) {
|
|
658
|
+
return ["google.com", "bing.com", "duckduckgo.com", "yahoo.com", "yandex.com"].some((e) => domain.includes(e));
|
|
659
|
+
}
|
|
660
|
+
isSocialPlatform(domain) {
|
|
661
|
+
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(
|
|
662
|
+
(p) => domain.includes(p)
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
isEmailClient(domain) {
|
|
666
|
+
return ["mail.google.com", "outlook.live.com", "mail.yahoo.com", "mail.aol.com"].some((c) => domain.includes(c));
|
|
667
|
+
}
|
|
668
|
+
getSessionCount() {
|
|
669
|
+
if (typeof window === "undefined") return 0;
|
|
670
|
+
try {
|
|
671
|
+
const stored = localStorage.getItem(this.SESSION_COUNT_KEY);
|
|
672
|
+
return stored ? parseInt(stored, 10) : 0;
|
|
673
|
+
} catch {
|
|
674
|
+
return 0;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
storeAttribution(attribution) {
|
|
678
|
+
if (typeof window === "undefined") return;
|
|
679
|
+
try {
|
|
680
|
+
sessionStorage.setItem(this.STORAGE_KEY, JSON.stringify(attribution));
|
|
681
|
+
localStorage.setItem(this.SESSION_COUNT_KEY, attribution.session_count.toString());
|
|
682
|
+
} catch {
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
isValidAttributionData(data) {
|
|
686
|
+
return data !== null && typeof data === "object" && "traffic_type" in data && "attribution_confidence" in data && "platform_id" in data && "is_embedded" in data;
|
|
687
|
+
}
|
|
688
|
+
getEmptyAttribution() {
|
|
689
|
+
return {
|
|
690
|
+
utm_source: null,
|
|
691
|
+
utm_medium: null,
|
|
692
|
+
utm_campaign: null,
|
|
693
|
+
utm_term: null,
|
|
694
|
+
utm_content: null,
|
|
695
|
+
utm_id: null,
|
|
696
|
+
utm_source_platform: null,
|
|
697
|
+
platform_id: "web",
|
|
698
|
+
is_embedded: false,
|
|
699
|
+
referrer_url: null,
|
|
700
|
+
referrer_domain: null,
|
|
701
|
+
referrer_source: null,
|
|
702
|
+
is_first_party_referrer: false,
|
|
703
|
+
traffic_type: "direct",
|
|
704
|
+
first_visit_timestamp: 0,
|
|
705
|
+
session_count: 0,
|
|
706
|
+
is_bot: false,
|
|
707
|
+
attribution_confidence: 0
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
function getAttributionData() {
|
|
712
|
+
return AttributionManager.getInstance().getAttribution();
|
|
713
|
+
}
|
|
714
|
+
|
|
412
715
|
// src/services/ads.ts
|
|
413
716
|
var AdsService = class {
|
|
414
717
|
config = {
|
|
@@ -1713,20 +2016,39 @@ var HyveClient = class {
|
|
|
1713
2016
|
return false;
|
|
1714
2017
|
}
|
|
1715
2018
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
2019
|
+
let parsedEventDetails = {};
|
|
2020
|
+
if (eventDetails) {
|
|
2021
|
+
if (typeof eventDetails === "string") {
|
|
2022
|
+
try {
|
|
2023
|
+
parsedEventDetails = JSON.parse(eventDetails);
|
|
2024
|
+
} catch {
|
|
2025
|
+
}
|
|
2026
|
+
} else {
|
|
2027
|
+
parsedEventDetails = eventDetails;
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
const attribution = getAttributionData();
|
|
2031
|
+
const enrichedEventDetails = {
|
|
2032
|
+
// Device info
|
|
2033
|
+
...getEssentialDeviceInfo(),
|
|
2034
|
+
// Attribution data
|
|
2035
|
+
...attribution,
|
|
2036
|
+
// Timestamp and session context
|
|
2037
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2038
|
+
session_id: this.sessionId,
|
|
2039
|
+
// Event-specific details can override any of the above
|
|
2040
|
+
...parsedEventDetails
|
|
1719
2041
|
};
|
|
1720
2042
|
const telemetryEvent = {
|
|
1721
2043
|
game_id: this.gameId,
|
|
1722
2044
|
session_id: this.sessionId,
|
|
1723
|
-
platform_id: platformId || null,
|
|
2045
|
+
platform_id: platformId || attribution.platform_id || null,
|
|
1724
2046
|
event_location: eventLocation,
|
|
1725
2047
|
event_category: eventCategory,
|
|
1726
2048
|
event_action: eventAction,
|
|
1727
2049
|
event_sub_category: eventSubCategory || null,
|
|
1728
2050
|
event_sub_action: eventSubAction || null,
|
|
1729
|
-
event_details:
|
|
2051
|
+
event_details: enrichedEventDetails
|
|
1730
2052
|
};
|
|
1731
2053
|
logger.debug("Sending telemetry event:", telemetryEvent);
|
|
1732
2054
|
const telemetryUrl = `${this.apiBaseUrl}/api/v1/analytics/send`;
|