@kywi-software/js 0.15.0 → 0.15.2
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/audience/behavioral-collector.d.ts +2 -1
- package/dist/audience/behavioral-collector.d.ts.map +1 -1
- package/dist/audience/evaluate.d.ts +9 -1
- package/dist/audience/evaluate.d.ts.map +1 -1
- package/dist/audience/query-collector.d.ts +15 -0
- package/dist/audience/query-collector.d.ts.map +1 -0
- package/dist/audience/selfid-api.d.ts +57 -0
- package/dist/audience/selfid-api.d.ts.map +1 -0
- package/dist/audience/selfid-collector.d.ts +2 -0
- package/dist/audience/selfid-collector.d.ts.map +1 -1
- package/dist/consent.d.ts.map +1 -1
- package/dist/feed.d.ts.map +1 -1
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/kywi.esm.js +244 -128
- package/dist/kywi.esm.js.map +4 -4
- package/dist/kywi.js +244 -128
- package/dist/kywi.js.map +4 -4
- package/package.json +2 -2
package/dist/kywi.esm.js
CHANGED
|
@@ -536,6 +536,98 @@ function bootExperiments(config = {}) {
|
|
|
536
536
|
return runtime;
|
|
537
537
|
}
|
|
538
538
|
|
|
539
|
+
// src/audience/selfid-collector.ts
|
|
540
|
+
var SELFID_KEY = "kywi_selfid";
|
|
541
|
+
function collectSelfId() {
|
|
542
|
+
const raw = readStorage(SELFID_KEY);
|
|
543
|
+
if (!raw) return {};
|
|
544
|
+
try {
|
|
545
|
+
const parsed = JSON.parse(raw);
|
|
546
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return {};
|
|
547
|
+
return parsed;
|
|
548
|
+
} catch {
|
|
549
|
+
return {};
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
function storeSelfId(responses) {
|
|
553
|
+
try {
|
|
554
|
+
localStorage.setItem(SELFID_KEY, JSON.stringify(responses));
|
|
555
|
+
} catch {
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
function clearStoredSelfId() {
|
|
559
|
+
try {
|
|
560
|
+
localStorage.removeItem(SELFID_KEY);
|
|
561
|
+
} catch {
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
function readStorage(key) {
|
|
565
|
+
try {
|
|
566
|
+
return localStorage.getItem(key);
|
|
567
|
+
} catch {
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// src/audience/selfid-api.ts
|
|
573
|
+
var DEFAULT_API_BASE = "/api/v1";
|
|
574
|
+
function resolveApiBase(explicit) {
|
|
575
|
+
if (explicit) return explicit;
|
|
576
|
+
const basePath = globalThis.Kywi?.context?.basePath;
|
|
577
|
+
if (!basePath || basePath === "/") return DEFAULT_API_BASE;
|
|
578
|
+
return `${basePath}/api/v1`;
|
|
579
|
+
}
|
|
580
|
+
function resolveCsrfToken(explicit) {
|
|
581
|
+
if (explicit !== void 0) return explicit;
|
|
582
|
+
return globalThis.Kywi?.context?.csrfToken ?? null;
|
|
583
|
+
}
|
|
584
|
+
function reloadPage() {
|
|
585
|
+
try {
|
|
586
|
+
window.location.reload();
|
|
587
|
+
} catch {
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
async function setSelfId(fields, options = {}) {
|
|
591
|
+
const merged = { ...collectSelfId() };
|
|
592
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
593
|
+
if (value === "") delete merged[key];
|
|
594
|
+
else merged[key] = value;
|
|
595
|
+
}
|
|
596
|
+
if (Object.keys(merged).length > 0) storeSelfId(merged);
|
|
597
|
+
else clearStoredSelfId();
|
|
598
|
+
const result = await submit(merged, options);
|
|
599
|
+
if (options.reload !== false && result !== null) reloadPage();
|
|
600
|
+
return result ?? { audience: null, persisted: false, fields: merged };
|
|
601
|
+
}
|
|
602
|
+
async function clearSelfId(options = {}) {
|
|
603
|
+
clearStoredSelfId();
|
|
604
|
+
const result = await submit({}, options);
|
|
605
|
+
if (options.reload !== false && result !== null) reloadPage();
|
|
606
|
+
return result ?? { audience: null, persisted: false, fields: {} };
|
|
607
|
+
}
|
|
608
|
+
async function submit(fields, options) {
|
|
609
|
+
const csrfToken = resolveCsrfToken(options.csrfToken);
|
|
610
|
+
try {
|
|
611
|
+
const res = await fetch(`${resolveApiBase(options.apiBase)}/kywi/self-id`, {
|
|
612
|
+
method: "POST",
|
|
613
|
+
headers: { "Content-Type": "application/json", ...csrfToken ? { "X-CSRF-Token": csrfToken } : {} },
|
|
614
|
+
body: JSON.stringify({
|
|
615
|
+
fields,
|
|
616
|
+
...options.audienceId ? { audienceId: options.audienceId } : {}
|
|
617
|
+
})
|
|
618
|
+
});
|
|
619
|
+
if (!res.ok) return null;
|
|
620
|
+
const body = await res.json().catch(() => null);
|
|
621
|
+
return {
|
|
622
|
+
audience: body?.data?.audience ?? null,
|
|
623
|
+
persisted: body?.data?.persisted === true,
|
|
624
|
+
fields
|
|
625
|
+
};
|
|
626
|
+
} catch {
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
539
631
|
// ../core/dist/audiences/types.js
|
|
540
632
|
function createEmptySignals() {
|
|
541
633
|
return {
|
|
@@ -543,6 +635,7 @@ function createEmptySignals() {
|
|
|
543
635
|
referrer: { raw: null, domain: null, sourceType: "direct" },
|
|
544
636
|
session: { pageViewCount: 0, totalPageViews: 0, sessionDuration: 0, entryPage: "/", pagesVisited: [] },
|
|
545
637
|
behavioral: { categoryScores: {}, totalScore: 0 },
|
|
638
|
+
query: {},
|
|
546
639
|
selfId: {},
|
|
547
640
|
identity: { visitorId: "", isKnown: false, maLeadId: null },
|
|
548
641
|
adapters: {},
|
|
@@ -603,6 +696,10 @@ function resolveSignalValue(signals, ref) {
|
|
|
603
696
|
return signals.session.entryPage;
|
|
604
697
|
if (ref === "session.pagesVisited")
|
|
605
698
|
return signals.session.pagesVisited.join(",");
|
|
699
|
+
if (ref.startsWith("query.")) {
|
|
700
|
+
const key = ref.slice(6);
|
|
701
|
+
return signals.query[key] ?? null;
|
|
702
|
+
}
|
|
606
703
|
if (ref.startsWith("selfId.")) {
|
|
607
704
|
const key = ref.slice(7);
|
|
608
705
|
return signals.selfId[key] ?? null;
|
|
@@ -770,6 +867,121 @@ function resolveAudiences(audiences, signals) {
|
|
|
770
867
|
return { winningAudienceId: allMatchedIds[0] ?? null, allMatchedIds, traces };
|
|
771
868
|
}
|
|
772
869
|
|
|
870
|
+
// src/audience/query-collector.ts
|
|
871
|
+
function collectQuery() {
|
|
872
|
+
const out = {};
|
|
873
|
+
if (typeof location === "undefined") return out;
|
|
874
|
+
new URLSearchParams(location.search).forEach((value, key) => {
|
|
875
|
+
if (key !== "" && !(key in out)) out[key] = value;
|
|
876
|
+
});
|
|
877
|
+
return out;
|
|
878
|
+
}
|
|
879
|
+
function entryPageFor(currentPath) {
|
|
880
|
+
if (currentPath.includes("?")) return currentPath;
|
|
881
|
+
const search = typeof location === "undefined" ? "" : location.search;
|
|
882
|
+
return search ? `${currentPath}${search}` : currentPath;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// src/cookies.ts
|
|
886
|
+
var COOKIE_NAMES = {
|
|
887
|
+
SIGNALS: "kywi_signals",
|
|
888
|
+
VISITOR: "kywi_visitor",
|
|
889
|
+
UTM: "kywi_utm",
|
|
890
|
+
AUDIENCE: "kywi_audience",
|
|
891
|
+
OPTOUT: "kywi_optout",
|
|
892
|
+
KNOWN: "kywi_known",
|
|
893
|
+
PREVIEW_INIT: "kywi_preview_init"
|
|
894
|
+
};
|
|
895
|
+
function readCookies() {
|
|
896
|
+
const map = /* @__PURE__ */ new Map();
|
|
897
|
+
if (typeof document === "undefined") return map;
|
|
898
|
+
for (const pair of document.cookie.split(";")) {
|
|
899
|
+
const trimmed = pair.trim();
|
|
900
|
+
const eqIdx = trimmed.indexOf("=");
|
|
901
|
+
if (eqIdx < 0) continue;
|
|
902
|
+
map.set(trimmed.slice(0, eqIdx), decodeURIComponent(trimmed.slice(eqIdx + 1)));
|
|
903
|
+
}
|
|
904
|
+
return map;
|
|
905
|
+
}
|
|
906
|
+
function setCookie(name, value, maxAge) {
|
|
907
|
+
let str = `${name}=${encodeURIComponent(value)}; Path=/; SameSite=Lax`;
|
|
908
|
+
if (maxAge !== void 0 && maxAge >= 0) str += `; Max-Age=${maxAge}`;
|
|
909
|
+
document.cookie = str;
|
|
910
|
+
}
|
|
911
|
+
function deleteCookie(name) {
|
|
912
|
+
document.cookie = `${name}=; Path=/; Max-Age=0`;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// src/consent.ts
|
|
916
|
+
var CONSENT_COOKIE = "kywi_consent";
|
|
917
|
+
var AUDIENCE_PIN_COOKIE = "kywi_audience";
|
|
918
|
+
var SWITCHER_PIN_PREFIX = "switcher:";
|
|
919
|
+
var COOKIE_CONSENT_CATEGORY = {
|
|
920
|
+
kywi_consent: "essential",
|
|
921
|
+
kywi_optout: "essential",
|
|
922
|
+
kywi_preview_init: "essential",
|
|
923
|
+
kywi_signals: "personalization",
|
|
924
|
+
kywi_visitor: "personalization",
|
|
925
|
+
kywi_utm: "personalization",
|
|
926
|
+
kywi_audience: "personalization",
|
|
927
|
+
kywi_known: "personalization",
|
|
928
|
+
kywi_entry: "personalization",
|
|
929
|
+
kywi_selfid: "personalization"
|
|
930
|
+
};
|
|
931
|
+
function getConsentState() {
|
|
932
|
+
const cookies = readCookies();
|
|
933
|
+
const raw = cookies.get(CONSENT_COOKIE);
|
|
934
|
+
if (!raw) return null;
|
|
935
|
+
let parsed;
|
|
936
|
+
try {
|
|
937
|
+
parsed = JSON.parse(raw);
|
|
938
|
+
} catch {
|
|
939
|
+
return null;
|
|
940
|
+
}
|
|
941
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
942
|
+
const obj = parsed;
|
|
943
|
+
return {
|
|
944
|
+
essential: true,
|
|
945
|
+
analytics: obj.analytics === true,
|
|
946
|
+
marketing: obj.marketing === true,
|
|
947
|
+
personalization: obj.personalization === true
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
function setConsent(prefs) {
|
|
951
|
+
const state = {
|
|
952
|
+
essential: true,
|
|
953
|
+
analytics: prefs.analytics ?? false,
|
|
954
|
+
marketing: prefs.marketing ?? false,
|
|
955
|
+
personalization: prefs.personalization ?? false
|
|
956
|
+
};
|
|
957
|
+
setCookie(CONSENT_COOKIE, JSON.stringify(state), 31536e3);
|
|
958
|
+
clearDeniedCookies(state);
|
|
959
|
+
}
|
|
960
|
+
function clearDeniedCookies(state) {
|
|
961
|
+
if (typeof document === "undefined") return [];
|
|
962
|
+
const cookies = readCookies();
|
|
963
|
+
const deleted = [];
|
|
964
|
+
for (const [name, category] of Object.entries(COOKIE_CONSENT_CATEGORY)) {
|
|
965
|
+
if (category === "essential") continue;
|
|
966
|
+
if (state && state[category] === true) continue;
|
|
967
|
+
if (isDeliberatePreference(name, cookies.get(name))) continue;
|
|
968
|
+
deleteCookie(name);
|
|
969
|
+
deleted.push(name);
|
|
970
|
+
}
|
|
971
|
+
return deleted;
|
|
972
|
+
}
|
|
973
|
+
function isDeliberatePreference(name, value) {
|
|
974
|
+
if (name !== AUDIENCE_PIN_COOKIE || value === void 0) return false;
|
|
975
|
+
return value.startsWith(SWITCHER_PIN_PREFIX) && value.length > SWITCHER_PIN_PREFIX.length;
|
|
976
|
+
}
|
|
977
|
+
function hasConsent(category, options = {}) {
|
|
978
|
+
if (options.requireConsent === false) return true;
|
|
979
|
+
if (category === "essential") return true;
|
|
980
|
+
const state = getConsentState();
|
|
981
|
+
if (!state) return false;
|
|
982
|
+
return state[category] === true;
|
|
983
|
+
}
|
|
984
|
+
|
|
773
985
|
// src/audience/behavioral-collector.ts
|
|
774
986
|
var SESSION_KEY = "kywi_session";
|
|
775
987
|
var TOTAL_VIEWS_KEY = "kywi_total_views";
|
|
@@ -802,10 +1014,11 @@ function getCategoryScores() {
|
|
|
802
1014
|
}
|
|
803
1015
|
return {};
|
|
804
1016
|
}
|
|
805
|
-
function collectBehavioral(currentPath, category) {
|
|
1017
|
+
function collectBehavioral(currentPath, category, gate = {}) {
|
|
806
1018
|
const session = getSession();
|
|
807
1019
|
session.pageViewCount += 1;
|
|
808
|
-
|
|
1020
|
+
const entryPage = session.entryPage || entryPageFor(currentPath);
|
|
1021
|
+
if (!session.entryPage && hasConsent("personalization", gate)) session.entryPage = entryPage;
|
|
809
1022
|
session.pagesVisited.push(currentPath);
|
|
810
1023
|
sessionStorage.setItem(SESSION_KEY, JSON.stringify(session));
|
|
811
1024
|
const totalViews = (Number(localStorage.getItem(TOTAL_VIEWS_KEY)) || 0) + 1;
|
|
@@ -817,26 +1030,11 @@ function collectBehavioral(currentPath, category) {
|
|
|
817
1030
|
localStorage.setItem(CATEGORY_SCORES_KEY, JSON.stringify(categoryScores));
|
|
818
1031
|
}
|
|
819
1032
|
return {
|
|
820
|
-
session: { pageViewCount: session.pageViewCount, totalPageViews: totalViews, sessionDuration: Math.floor((Date.now() - sessionStart) / 1e3), entryPage
|
|
1033
|
+
session: { pageViewCount: session.pageViewCount, totalPageViews: totalViews, sessionDuration: Math.floor((Date.now() - sessionStart) / 1e3), entryPage, pagesVisited: session.pagesVisited },
|
|
821
1034
|
behavioral: { categoryScores, totalScore: 0 }
|
|
822
1035
|
};
|
|
823
1036
|
}
|
|
824
1037
|
|
|
825
|
-
// src/audience/selfid-collector.ts
|
|
826
|
-
var SELFID_KEY = "kywi_selfid";
|
|
827
|
-
function collectSelfId() {
|
|
828
|
-
const raw = localStorage.getItem(SELFID_KEY);
|
|
829
|
-
if (!raw) return {};
|
|
830
|
-
try {
|
|
831
|
-
return JSON.parse(raw);
|
|
832
|
-
} catch {
|
|
833
|
-
return {};
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
function storeSelfId(responses) {
|
|
837
|
-
localStorage.setItem(SELFID_KEY, JSON.stringify(responses));
|
|
838
|
-
}
|
|
839
|
-
|
|
840
1038
|
// src/audience/evaluate.ts
|
|
841
1039
|
function merge(base, partial) {
|
|
842
1040
|
return {
|
|
@@ -844,17 +1042,18 @@ function merge(base, partial) {
|
|
|
844
1042
|
referrer: partial.referrer ?? base.referrer,
|
|
845
1043
|
session: partial.session ?? base.session,
|
|
846
1044
|
behavioral: partial.behavioral ?? base.behavioral,
|
|
1045
|
+
query: { ...base.query, ...partial.query },
|
|
847
1046
|
selfId: { ...base.selfId, ...partial.selfId },
|
|
848
1047
|
identity: partial.identity ?? base.identity,
|
|
849
1048
|
adapters: { ...base.adapters, ...partial.adapters },
|
|
850
1049
|
meta: { ...base.meta, ...partial.meta }
|
|
851
1050
|
};
|
|
852
1051
|
}
|
|
853
|
-
function evaluateClientSide(audiences, serverSignals, currentPath, pageCategory) {
|
|
1052
|
+
function evaluateClientSide(audiences, serverSignals, currentPath, pageCategory, gate = {}) {
|
|
854
1053
|
let signals = merge(createEmptySignals(), serverSignals);
|
|
855
|
-
const client = collectBehavioral(currentPath, pageCategory);
|
|
1054
|
+
const client = collectBehavioral(currentPath, pageCategory, gate);
|
|
856
1055
|
const selfId = collectSelfId();
|
|
857
|
-
signals = merge(signals, { session: client.session, behavioral: client.behavioral, selfId, meta: { ...signals.meta, resolvedAt: "client" } });
|
|
1056
|
+
signals = merge(signals, { session: client.session, behavioral: client.behavioral, query: collectQuery(), selfId, meta: { ...signals.meta, resolvedAt: "client" } });
|
|
858
1057
|
const { winningAudienceId, allMatchedIds } = resolveAudiences(audiences, signals);
|
|
859
1058
|
const isOptedOut2 = signals.meta.isOptedOut;
|
|
860
1059
|
return { winningAudienceId: isOptedOut2 ? null : winningAudienceId, allMatchedIds, signals, isOptedOut: isOptedOut2 };
|
|
@@ -882,36 +1081,6 @@ function patchVariantContainers(winningAudienceId) {
|
|
|
882
1081
|
}
|
|
883
1082
|
}
|
|
884
1083
|
|
|
885
|
-
// src/cookies.ts
|
|
886
|
-
var COOKIE_NAMES = {
|
|
887
|
-
SIGNALS: "kywi_signals",
|
|
888
|
-
VISITOR: "kywi_visitor",
|
|
889
|
-
UTM: "kywi_utm",
|
|
890
|
-
AUDIENCE: "kywi_audience",
|
|
891
|
-
OPTOUT: "kywi_optout",
|
|
892
|
-
KNOWN: "kywi_known",
|
|
893
|
-
PREVIEW_INIT: "kywi_preview_init"
|
|
894
|
-
};
|
|
895
|
-
function readCookies() {
|
|
896
|
-
const map = /* @__PURE__ */ new Map();
|
|
897
|
-
if (typeof document === "undefined") return map;
|
|
898
|
-
for (const pair of document.cookie.split(";")) {
|
|
899
|
-
const trimmed = pair.trim();
|
|
900
|
-
const eqIdx = trimmed.indexOf("=");
|
|
901
|
-
if (eqIdx < 0) continue;
|
|
902
|
-
map.set(trimmed.slice(0, eqIdx), decodeURIComponent(trimmed.slice(eqIdx + 1)));
|
|
903
|
-
}
|
|
904
|
-
return map;
|
|
905
|
-
}
|
|
906
|
-
function setCookie(name, value, maxAge) {
|
|
907
|
-
let str = `${name}=${encodeURIComponent(value)}; Path=/; SameSite=Lax`;
|
|
908
|
-
if (maxAge !== void 0 && maxAge >= 0) str += `; Max-Age=${maxAge}`;
|
|
909
|
-
document.cookie = str;
|
|
910
|
-
}
|
|
911
|
-
function deleteCookie(name) {
|
|
912
|
-
document.cookie = `${name}=; Path=/; Max-Age=0`;
|
|
913
|
-
}
|
|
914
|
-
|
|
915
1084
|
// src/audience/transparency.ts
|
|
916
1085
|
var COLLAPSED_KEY = "kywi_transparency_collapsed";
|
|
917
1086
|
var LEGACY_DISMISSED_KEY = "kywi_transparency_dismissed";
|
|
@@ -919,10 +1088,10 @@ var ROOT_ID = "kywi-transparency";
|
|
|
919
1088
|
var PANEL_ID = "kywi-transparency-panel";
|
|
920
1089
|
var TITLE_ID = "kywi-transparency-title";
|
|
921
1090
|
var SWITCHER_LABEL_ID = "kywi-transparency-switcher-label";
|
|
922
|
-
var
|
|
1091
|
+
var DEFAULT_API_BASE2 = "/api/v1";
|
|
923
1092
|
var lastState = null;
|
|
924
1093
|
var forcedOpen = false;
|
|
925
|
-
function
|
|
1094
|
+
function readStorage2(key) {
|
|
926
1095
|
try {
|
|
927
1096
|
return localStorage.getItem(key);
|
|
928
1097
|
} catch {
|
|
@@ -942,12 +1111,12 @@ function removeStorage(key) {
|
|
|
942
1111
|
}
|
|
943
1112
|
}
|
|
944
1113
|
function isCollapsed() {
|
|
945
|
-
if (
|
|
1114
|
+
if (readStorage2(LEGACY_DISMISSED_KEY) === "1") {
|
|
946
1115
|
removeStorage(LEGACY_DISMISSED_KEY);
|
|
947
1116
|
writeStorage(COLLAPSED_KEY, "1");
|
|
948
1117
|
return true;
|
|
949
1118
|
}
|
|
950
|
-
return
|
|
1119
|
+
return readStorage2(COLLAPSED_KEY) !== "0";
|
|
951
1120
|
}
|
|
952
1121
|
function setCollapsed(collapsed) {
|
|
953
1122
|
writeStorage(COLLAPSED_KEY, collapsed ? "1" : "0");
|
|
@@ -966,7 +1135,7 @@ function hasPin() {
|
|
|
966
1135
|
return readCookies().has(COOKIE_NAMES.AUDIENCE);
|
|
967
1136
|
}
|
|
968
1137
|
async function pinAudience(audienceId, opts = {}) {
|
|
969
|
-
const apiBase = opts.apiBase ??
|
|
1138
|
+
const apiBase = opts.apiBase ?? DEFAULT_API_BASE2;
|
|
970
1139
|
try {
|
|
971
1140
|
const res = await fetch(`${apiBase}/kywi/audience`, {
|
|
972
1141
|
method: "POST",
|
|
@@ -1228,74 +1397,6 @@ function readServerMeta() {
|
|
|
1228
1397
|
return { audienceId: m("audience-id"), experimentId: m("experiment-id"), variantId: m("variant-id"), visitorId: m("visitor-id") ?? "" };
|
|
1229
1398
|
}
|
|
1230
1399
|
|
|
1231
|
-
// src/consent.ts
|
|
1232
|
-
var CONSENT_COOKIE = "kywi_consent";
|
|
1233
|
-
var AUDIENCE_PIN_COOKIE = "kywi_audience";
|
|
1234
|
-
var SWITCHER_PIN_PREFIX = "switcher:";
|
|
1235
|
-
var COOKIE_CONSENT_CATEGORY = {
|
|
1236
|
-
kywi_consent: "essential",
|
|
1237
|
-
kywi_optout: "essential",
|
|
1238
|
-
kywi_preview_init: "essential",
|
|
1239
|
-
kywi_signals: "personalization",
|
|
1240
|
-
kywi_visitor: "personalization",
|
|
1241
|
-
kywi_utm: "personalization",
|
|
1242
|
-
kywi_audience: "personalization",
|
|
1243
|
-
kywi_known: "personalization"
|
|
1244
|
-
};
|
|
1245
|
-
function getConsentState() {
|
|
1246
|
-
const cookies = readCookies();
|
|
1247
|
-
const raw = cookies.get(CONSENT_COOKIE);
|
|
1248
|
-
if (!raw) return null;
|
|
1249
|
-
let parsed;
|
|
1250
|
-
try {
|
|
1251
|
-
parsed = JSON.parse(raw);
|
|
1252
|
-
} catch {
|
|
1253
|
-
return null;
|
|
1254
|
-
}
|
|
1255
|
-
if (typeof parsed !== "object" || parsed === null) return null;
|
|
1256
|
-
const obj = parsed;
|
|
1257
|
-
return {
|
|
1258
|
-
essential: true,
|
|
1259
|
-
analytics: obj.analytics === true,
|
|
1260
|
-
marketing: obj.marketing === true,
|
|
1261
|
-
personalization: obj.personalization === true
|
|
1262
|
-
};
|
|
1263
|
-
}
|
|
1264
|
-
function setConsent(prefs) {
|
|
1265
|
-
const state = {
|
|
1266
|
-
essential: true,
|
|
1267
|
-
analytics: prefs.analytics ?? false,
|
|
1268
|
-
marketing: prefs.marketing ?? false,
|
|
1269
|
-
personalization: prefs.personalization ?? false
|
|
1270
|
-
};
|
|
1271
|
-
setCookie(CONSENT_COOKIE, JSON.stringify(state), 31536e3);
|
|
1272
|
-
clearDeniedCookies(state);
|
|
1273
|
-
}
|
|
1274
|
-
function clearDeniedCookies(state) {
|
|
1275
|
-
if (typeof document === "undefined") return [];
|
|
1276
|
-
const cookies = readCookies();
|
|
1277
|
-
const deleted = [];
|
|
1278
|
-
for (const [name, category] of Object.entries(COOKIE_CONSENT_CATEGORY)) {
|
|
1279
|
-
if (category === "essential") continue;
|
|
1280
|
-
if (state && state[category] === true) continue;
|
|
1281
|
-
if (isDeliberatePreference(name, cookies.get(name))) continue;
|
|
1282
|
-
deleteCookie(name);
|
|
1283
|
-
deleted.push(name);
|
|
1284
|
-
}
|
|
1285
|
-
return deleted;
|
|
1286
|
-
}
|
|
1287
|
-
function isDeliberatePreference(name, value) {
|
|
1288
|
-
if (name !== AUDIENCE_PIN_COOKIE || value === void 0) return false;
|
|
1289
|
-
return value.startsWith(SWITCHER_PIN_PREFIX) && value.length > SWITCHER_PIN_PREFIX.length;
|
|
1290
|
-
}
|
|
1291
|
-
function hasConsent(category, options = {}) {
|
|
1292
|
-
if (options.requireConsent === false) return true;
|
|
1293
|
-
if (category === "essential") return true;
|
|
1294
|
-
const state = getConsentState();
|
|
1295
|
-
if (!state) return false;
|
|
1296
|
-
return state[category] === true;
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
1400
|
// src/audience/adapter-runner.ts
|
|
1300
1401
|
var CACHE_PREFIX = "kywi_adapter_";
|
|
1301
1402
|
function getCached(adapterId) {
|
|
@@ -1618,7 +1719,7 @@ function renderPersonalizationBadge(info = {}) {
|
|
|
1618
1719
|
}
|
|
1619
1720
|
|
|
1620
1721
|
// src/audience/index.ts
|
|
1621
|
-
function
|
|
1722
|
+
function resolveApiBase2(explicit) {
|
|
1622
1723
|
if (explicit) return explicit;
|
|
1623
1724
|
const basePath = Kywi.context?.basePath;
|
|
1624
1725
|
if (!basePath || basePath === "/") return "/api/v1";
|
|
@@ -1626,7 +1727,7 @@ function resolveApiBase(explicit) {
|
|
|
1626
1727
|
}
|
|
1627
1728
|
async function bootAudienceEngine(config) {
|
|
1628
1729
|
const { audiences, currentPath, pageCategory, serverSignals } = config;
|
|
1629
|
-
const apiBase =
|
|
1730
|
+
const apiBase = resolveApiBase2(config.apiBase);
|
|
1630
1731
|
checkPreviewInit();
|
|
1631
1732
|
const serverMeta = readServerMeta();
|
|
1632
1733
|
const previewId = getPreviewAudienceId();
|
|
@@ -1653,7 +1754,7 @@ async function bootAudienceEngine(config) {
|
|
|
1653
1754
|
const adapterResults = await runClientAdapters(config.adapters, merged, apiBase);
|
|
1654
1755
|
merged.adapters = { ...merged.adapters, ...adapterResults };
|
|
1655
1756
|
}
|
|
1656
|
-
const result = evaluateClientSide(audiences, merged, currentPath, pageCategory);
|
|
1757
|
+
const result = evaluateClientSide(audiences, merged, currentPath, pageCategory, consentGate);
|
|
1657
1758
|
const rawPin = cookies.get(COOKIE_NAMES.AUDIENCE) ?? null;
|
|
1658
1759
|
const pinnedId = rawPin?.startsWith("switcher:") ? rawPin.slice("switcher:".length) || null : rawPin;
|
|
1659
1760
|
const isPinned = !result.isOptedOut && pinnedId !== null && activeAudiences.some((a) => a.id === pinnedId);
|
|
@@ -1757,6 +1858,19 @@ var Kywi = {
|
|
|
1757
1858
|
}
|
|
1758
1859
|
}
|
|
1759
1860
|
},
|
|
1861
|
+
/**
|
|
1862
|
+
* Record who the visitor says they are, and resolve their audience
|
|
1863
|
+
* (kywi-cms#200). Writes the browser-side answers, posts them to the
|
|
1864
|
+
* consent-gated runtime endpoint, and reloads so the SERVER can re-render
|
|
1865
|
+
* with the resolved audience pinned — which is the only way to reach a
|
|
1866
|
+
* variant arm, since every losing arm is pruned server-side (#167).
|
|
1867
|
+
*
|
|
1868
|
+
* On the global because a site's own "What brings you here?" control needs
|
|
1869
|
+
* it: the built-in widget's write path is module-private.
|
|
1870
|
+
*/
|
|
1871
|
+
setSelfId,
|
|
1872
|
+
/** Forget the visitor's self-identification and un-pin their audience. */
|
|
1873
|
+
clearSelfId,
|
|
1760
1874
|
getEntity: null,
|
|
1761
1875
|
getFeed: null,
|
|
1762
1876
|
renderFeed: null,
|
|
@@ -1797,12 +1911,14 @@ export {
|
|
|
1797
1911
|
bootAudienceEngine,
|
|
1798
1912
|
bootExperiments,
|
|
1799
1913
|
clearDeniedCookies,
|
|
1914
|
+
clearSelfId,
|
|
1800
1915
|
enhanceNav,
|
|
1801
1916
|
getConsentState,
|
|
1802
1917
|
hasConsent,
|
|
1803
1918
|
initNavMenus,
|
|
1804
1919
|
openTransparencyPanel,
|
|
1805
1920
|
renderTransparencyPanel,
|
|
1806
|
-
setConsent
|
|
1921
|
+
setConsent,
|
|
1922
|
+
setSelfId
|
|
1807
1923
|
};
|
|
1808
1924
|
//# sourceMappingURL=kywi.esm.js.map
|