@xyo-network/react-advertising 4.1.6 → 4.1.8

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.
@@ -5,6 +5,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
5
5
  import { usePromise } from "@xylabs/react-promise";
6
6
  import { UtmSchema } from "@xyo-network/advertising-payload-plugins";
7
7
  import { useMemo as useMemo2 } from "react";
8
+ import { useSearchParams as useSearchParams2 } from "react-router-dom";
8
9
 
9
10
  // src/utm/lib/UtmStorageArchivist.ts
10
11
  import { isUtm } from "@xyo-network/advertising-payload-plugins";
@@ -83,8 +84,9 @@ var useDefaultUtmPageState = /* @__PURE__ */ __name(() => useDefaultPageState({
83
84
  }), "useDefaultUtmPageState");
84
85
 
85
86
  // src/utm/hooks/useCaptureUtmLocation.ts
86
- var useCaptureUtmLocation = /* @__PURE__ */ __name(() => {
87
+ var useCaptureUtmLocation = /* @__PURE__ */ __name((clearAfterCapture = true) => {
87
88
  const [{ utm_campaign, utm_content, utm_medium, utm_source, utm_term }] = useDefaultUtmPageState();
89
+ const [, setSearchParams] = useSearchParams2();
88
90
  const [sessionStorageArchivist, error] = usePromise(async () => {
89
91
  return await UtmStorageArchivist();
90
92
  }, []);
@@ -92,12 +94,26 @@ var useCaptureUtmLocation = /* @__PURE__ */ __name(() => {
92
94
  const utm = {
93
95
  schema: UtmSchema
94
96
  };
95
- if (utm_campaign) utm.utm_campaign = utm_campaign;
96
- if (utm_content) utm.utm_content = utm_content;
97
- if (utm_medium) utm.utm_medium = utm_medium;
98
- if (utm_source) utm.utm_source = utm_source;
99
- if (utm_term) utm.utm_term = utm_term;
100
- return utm;
97
+ const utmParams = {
98
+ utm_campaign,
99
+ utm_content,
100
+ utm_medium,
101
+ utm_source,
102
+ utm_term
103
+ };
104
+ const foundUpdatedUtmParams = Object.entries(utmParams).some(([key, value]) => {
105
+ return key.includes("utm_") && value;
106
+ });
107
+ if (foundUpdatedUtmParams) {
108
+ if (utm_campaign) utm.utm_campaign = utm_campaign;
109
+ if (utm_content) utm.utm_content = utm_content;
110
+ if (utm_medium) utm.utm_medium = utm_medium;
111
+ if (utm_source) utm.utm_source = utm_source;
112
+ if (utm_term) utm.utm_term = utm_term;
113
+ return utm;
114
+ } else {
115
+ return null;
116
+ }
101
117
  }, [
102
118
  utm_campaign,
103
119
  utm_content,
@@ -110,10 +126,20 @@ var useCaptureUtmLocation = /* @__PURE__ */ __name(() => {
110
126
  await sessionStorageArchivist.insert([
111
127
  utmPayload
112
128
  ]);
129
+ if (clearAfterCapture) {
130
+ setSearchParams(() => {
131
+ const newParams = new URLSearchParams();
132
+ for (const value of Object.values(UtmQueryParamStrings)) {
133
+ newParams.delete(value);
134
+ }
135
+ return newParams;
136
+ });
137
+ }
113
138
  }
114
139
  }, [
115
140
  sessionStorageArchivist,
116
- utmPayload
141
+ utmPayload,
142
+ clearAfterCapture
117
143
  ]);
118
144
  return {
119
145
  utmPayload,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utm/hooks/useCaptureUtmLocation.ts","../../src/utm/lib/UtmStorageArchivist.ts","../../src/utm/hooks/useDefaultPageState.ts","../../src/utm/hooks/useDefaultUtmPageState.ts"],"sourcesContent":["import { usePromise } from '@xylabs/react-promise'\nimport { type Utm, UtmSchema } from '@xyo-network/advertising-payload-plugins'\nimport { useMemo } from 'react'\n\nimport { UtmStorageArchivist } from '../lib/index.ts'\nimport { useDefaultUtmPageState } from './useDefaultUtmPageState.ts'\n\nexport const useCaptureUtmLocation = () => {\n const [{\n utm_campaign, utm_content, utm_medium, utm_source, utm_term,\n }] = useDefaultUtmPageState()\n\n const [sessionStorageArchivist, error] = usePromise(async () => {\n return await UtmStorageArchivist()\n }, [])\n\n const utmPayload = useMemo(() => {\n // Construct the base UTM payload\n const utm: Utm = { schema: UtmSchema }\n\n // Conditionally add all the UTM parameters present\n if (utm_campaign) utm.utm_campaign = utm_campaign\n if (utm_content) utm.utm_content = utm_content\n if (utm_medium) utm.utm_medium = utm_medium\n if (utm_source) utm.utm_source = utm_source\n if (utm_term) utm.utm_term = utm_term\n\n return utm\n }, [utm_campaign, utm_content, utm_medium, utm_source, utm_term])\n\n const [,insertError] = usePromise(async () => {\n if (utmPayload && sessionStorageArchivist) {\n await sessionStorageArchivist.insert([utmPayload])\n }\n }, [sessionStorageArchivist, utmPayload])\n\n return { utmPayload, error: error ?? insertError }\n}\n","import type { Utm } from '@xyo-network/advertising-payload-plugins'\nimport { isUtm } from '@xyo-network/advertising-payload-plugins'\nimport { StorageArchivist, StorageArchivistConfigSchema } from '@xyo-network/archivist-storage'\n\nconst STORAGE_NAME_SPACE = 'utm' as const\n\nlet archivist: StorageArchivist | undefined\n\n/**\n * Find or create a single instance of the UtmStorageArchivist\n * @returns Archivist instance\n */\nexport const UtmStorageArchivist = async () => {\n if (archivist) {\n return archivist\n } else {\n archivist = await StorageArchivist.create({\n account: 'random',\n config: {\n schema: StorageArchivistConfigSchema, namespace: STORAGE_NAME_SPACE, type: 'session',\n },\n })\n return archivist\n }\n}\n\nexport const LatestUtmPayload = async (): Promise<Utm | undefined> => {\n const archivist = await UtmStorageArchivist()\n return (await archivist.all()).findLast(isUtm) as Utm\n}\n","import { useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\n\nimport type { PageStateKeys } from '../lib/index.ts'\n\nexport interface DefaultPageStateParams<TQueryParams extends PageStateKeys = PageStateKeys> {\n queryParams: TQueryParams\n}\n\nexport type DefaultPageStateReturn<TPageStateKeys extends PageStateKeys = PageStateKeys> = [\n Record<TPageStateKeys[number], string>,\n (source: keyof DefaultPageStateParams, key: TPageStateKeys[number], value: string) => void,\n]\n\n/**\n * Hook to get default page state as key value pairs from various sources. It provides a convenient abstraction over free form\n * page state like query params by narrowing the used params and centralizing their logic.\n *\n * Future work could include adding support for localStorage, sessionStorage, and precedence of sources.\n * @param defaultPageStateParams various sources of default page state (i.e. queryParams, localStorage, etc.)\n * @returns\n */\nexport const useDefaultPageState = <TQueryParams extends PageStateKeys = PageStateKeys>(\n { queryParams }: DefaultPageStateParams<TQueryParams>,\n): DefaultPageStateReturn<TQueryParams> => {\n const [searchParams, setSearchParams] = useSearchParams()\n\n const patchDefaultPageState = (source: keyof DefaultPageStateParams, key: TQueryParams[number], value: string) => {\n switch (source) {\n case 'queryParams': {\n setSearchParams((prevSearchParams) => {\n const newSearchParams = new URLSearchParams(prevSearchParams)\n newSearchParams.set(key, value)\n return newSearchParams\n })\n break\n }\n default: {\n throw new Error(`Invalid source for default page state: ${source}`)\n }\n }\n }\n\n const queryParamsState = useMemo(() => {\n if (!queryParams) return {} as Record<TQueryParams[number], string>\n let defaultState = {} as Record<TQueryParams[number], string>\n for (const [key, value] of searchParams.entries()) {\n if (queryParams.includes(key)) {\n defaultState[key as TQueryParams[number]] = value\n }\n }\n return defaultState\n }, [searchParams, queryParams])\n\n return [queryParamsState, patchDefaultPageState]\n}\n","import { useDefaultPageState } from './useDefaultPageState.ts'\n\nexport const UtmQueryParamStrings = {\n utmCampaign: 'utm_campaign',\n utmContent: 'utm_content',\n utmMedium: 'utm_medium',\n utmSource: 'utm_source',\n utmTerm: 'utm_term',\n} as const\n\nexport type UtmQueryParams = typeof UtmQueryParamStrings[keyof typeof UtmQueryParamStrings]\n\n/** Get the default page state for utm values from specific query params */\nexport const useDefaultUtmPageState = () => useDefaultPageState<UtmQueryParams[]>({ queryParams: Object.values(UtmQueryParamStrings) })\n"],"mappings":";;;;AAAA,SAASA,kBAAkB;AAC3B,SAAmBC,iBAAiB;AACpC,SAASC,WAAAA,gBAAe;;;ACDxB,SAASC,aAAa;AACtB,SAASC,kBAAkBC,oCAAoC;AAE/D,IAAMC,qBAAqB;AAE3B,IAAIC;AAMG,IAAMC,sBAAsB,mCAAA;AACjC,MAAID,WAAW;AACb,WAAOA;EACT,OAAO;AACLA,gBAAY,MAAME,iBAAiBC,OAAO;MACxCC,SAAS;MACTC,QAAQ;QACNC,QAAQC;QAA8BC,WAAWT;QAAoBU,MAAM;MAC7E;IACF,CAAA;AACA,WAAOT;EACT;AACF,GAZmC;AAc5B,IAAMU,mBAAmB,mCAAA;AAC9B,QAAMV,aAAY,MAAMC,oBAAAA;AACxB,UAAQ,MAAMD,WAAUW,IAAG,GAAIC,SAASC,KAAAA;AAC1C,GAHgC;;;AC1BhC,SAASC,eAAe;AACxB,SAASC,uBAAuB;AAqBzB,IAAMC,sBAAsB,wBACjC,EAAEC,YAAW,MAAwC;AAErD,QAAM,CAACC,cAAcC,eAAAA,IAAmBC,gBAAAA;AAExC,QAAMC,wBAAwB,wBAACC,QAAsCC,KAA2BC,UAAAA;AAC9F,YAAQF,QAAAA;MACN,KAAK,eAAe;AAClBH,wBAAgB,CAACM,qBAAAA;AACf,gBAAMC,kBAAkB,IAAIC,gBAAgBF,gBAAAA;AAC5CC,0BAAgBE,IAAIL,KAAKC,KAAAA;AACzB,iBAAOE;QACT,CAAA;AACA;MACF;MACA,SAAS;AACP,cAAM,IAAIG,MAAM,0CAA0CP,MAAAA,EAAQ;MACpE;IACF;EACF,GAd8B;AAgB9B,QAAMQ,mBAAmBC,QAAQ,MAAA;AAC/B,QAAI,CAACd,YAAa,QAAO,CAAC;AAC1B,QAAIe,eAAe,CAAC;AACpB,eAAW,CAACT,KAAKC,KAAAA,KAAUN,aAAae,QAAO,GAAI;AACjD,UAAIhB,YAAYiB,SAASX,GAAAA,GAAM;AAC7BS,qBAAaT,GAAAA,IAA+BC;MAC9C;IACF;AACA,WAAOQ;EACT,GAAG;IAACd;IAAcD;GAAY;AAE9B,SAAO;IAACa;IAAkBT;;AAC5B,GAjCmC;;;ACpB5B,IAAMc,uBAAuB;EAClCC,aAAa;EACbC,YAAY;EACZC,WAAW;EACXC,WAAW;EACXC,SAAS;AACX;AAKO,IAAMC,yBAAyB,6BAAMC,oBAAsC;EAAEC,aAAaC,OAAOC,OAAOV,oBAAAA;AAAsB,CAAA,GAA/F;;;AHN/B,IAAMW,wBAAwB,6BAAA;AACnC,QAAM,CAAC,EACLC,cAAcC,aAAaC,YAAYC,YAAYC,SAAQ,CAC5D,IAAIC,uBAAAA;AAEL,QAAM,CAACC,yBAAyBC,KAAAA,IAASC,WAAW,YAAA;AAClD,WAAO,MAAMC,oBAAAA;EACf,GAAG,CAAA,CAAE;AAEL,QAAMC,aAAaC,SAAQ,MAAA;AAEzB,UAAMC,MAAW;MAAEC,QAAQC;IAAU;AAGrC,QAAId,aAAcY,KAAIZ,eAAeA;AACrC,QAAIC,YAAaW,KAAIX,cAAcA;AACnC,QAAIC,WAAYU,KAAIV,aAAaA;AACjC,QAAIC,WAAYS,KAAIT,aAAaA;AACjC,QAAIC,SAAUQ,KAAIR,WAAWA;AAE7B,WAAOQ;EACT,GAAG;IAACZ;IAAcC;IAAaC;IAAYC;IAAYC;GAAS;AAEhE,QAAM,CAAA,EAAEW,WAAAA,IAAeP,WAAW,YAAA;AAChC,QAAIE,cAAcJ,yBAAyB;AACzC,YAAMA,wBAAwBU,OAAO;QAACN;OAAW;IACnD;EACF,GAAG;IAACJ;IAAyBI;GAAW;AAExC,SAAO;IAAEA;IAAYH,OAAOA,SAASQ;EAAY;AACnD,GA9BqC;","names":["usePromise","UtmSchema","useMemo","isUtm","StorageArchivist","StorageArchivistConfigSchema","STORAGE_NAME_SPACE","archivist","UtmStorageArchivist","StorageArchivist","create","account","config","schema","StorageArchivistConfigSchema","namespace","type","LatestUtmPayload","all","findLast","isUtm","useMemo","useSearchParams","useDefaultPageState","queryParams","searchParams","setSearchParams","useSearchParams","patchDefaultPageState","source","key","value","prevSearchParams","newSearchParams","URLSearchParams","set","Error","queryParamsState","useMemo","defaultState","entries","includes","UtmQueryParamStrings","utmCampaign","utmContent","utmMedium","utmSource","utmTerm","useDefaultUtmPageState","useDefaultPageState","queryParams","Object","values","useCaptureUtmLocation","utm_campaign","utm_content","utm_medium","utm_source","utm_term","useDefaultUtmPageState","sessionStorageArchivist","error","usePromise","UtmStorageArchivist","utmPayload","useMemo","utm","schema","UtmSchema","insertError","insert"]}
1
+ {"version":3,"sources":["../../src/utm/hooks/useCaptureUtmLocation.ts","../../src/utm/lib/UtmStorageArchivist.ts","../../src/utm/hooks/useDefaultPageState.ts","../../src/utm/hooks/useDefaultUtmPageState.ts"],"sourcesContent":["import { usePromise } from '@xylabs/react-promise'\nimport { type Utm, UtmSchema } from '@xyo-network/advertising-payload-plugins'\nimport { useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\n\nimport { UtmStorageArchivist } from '../lib/index.ts'\nimport { useDefaultUtmPageState, UtmQueryParamStrings } from './useDefaultUtmPageState.ts'\n\nexport const useCaptureUtmLocation = (clearAfterCapture = true) => {\n const [{\n utm_campaign, utm_content, utm_medium, utm_source, utm_term,\n }] = useDefaultUtmPageState()\n const [,setSearchParams] = useSearchParams()\n\n const [sessionStorageArchivist, error] = usePromise(async () => {\n return await UtmStorageArchivist()\n }, [])\n\n const utmPayload = useMemo(() => {\n // Construct the base UTM payload\n const utm: Utm = { schema: UtmSchema }\n\n // determine if there's a utm field that still has a value\n // if there is none, it means that either the page loaded\n // with none or they've already been captured\n const utmParams = {\n utm_campaign, utm_content, utm_medium, utm_source, utm_term,\n }\n const foundUpdatedUtmParams = Object.entries(utmParams).some(([key, value]) => {\n return key.includes('utm_') && value\n })\n\n if (foundUpdatedUtmParams) {\n // Conditionally add all the UTM parameters present\n if (utm_campaign) utm.utm_campaign = utm_campaign\n if (utm_content) utm.utm_content = utm_content\n if (utm_medium) utm.utm_medium = utm_medium\n if (utm_source) utm.utm_source = utm_source\n if (utm_term) utm.utm_term = utm_term\n\n return utm\n } else {\n return null\n }\n }, [utm_campaign, utm_content, utm_medium, utm_source, utm_term])\n\n const [,insertError] = usePromise(async () => {\n if (utmPayload && sessionStorageArchivist) {\n // insert params into session storage\n await sessionStorageArchivist.insert([utmPayload])\n\n if (clearAfterCapture) {\n // remove the utm params from the URL\n setSearchParams(() => {\n const newParams = new URLSearchParams()\n for (const value of Object.values(UtmQueryParamStrings)) {\n newParams.delete(value)\n }\n return newParams\n })\n }\n }\n }, [sessionStorageArchivist, utmPayload, clearAfterCapture])\n\n return { utmPayload, error: error ?? insertError }\n}\n","import type { Utm } from '@xyo-network/advertising-payload-plugins'\nimport { isUtm } from '@xyo-network/advertising-payload-plugins'\nimport { StorageArchivist, StorageArchivistConfigSchema } from '@xyo-network/archivist-storage'\n\nconst STORAGE_NAME_SPACE = 'utm' as const\n\nlet archivist: StorageArchivist | undefined\n\n/**\n * Find or create a single instance of the UtmStorageArchivist\n * @returns Archivist instance\n */\nexport const UtmStorageArchivist = async () => {\n if (archivist) {\n return archivist\n } else {\n archivist = await StorageArchivist.create({\n account: 'random',\n config: {\n schema: StorageArchivistConfigSchema, namespace: STORAGE_NAME_SPACE, type: 'session',\n },\n })\n return archivist\n }\n}\n\nexport const LatestUtmPayload = async (): Promise<Utm | undefined> => {\n const archivist = await UtmStorageArchivist()\n return (await archivist.all()).findLast(isUtm) as Utm\n}\n","import { useMemo } from 'react'\nimport { useSearchParams } from 'react-router-dom'\n\nimport type { PageStateKeys } from '../lib/index.ts'\n\nexport interface DefaultPageStateParams<TQueryParams extends PageStateKeys = PageStateKeys> {\n queryParams: TQueryParams\n}\n\nexport type DefaultPageStateReturn<TPageStateKeys extends PageStateKeys = PageStateKeys> = [\n Record<TPageStateKeys[number], string>,\n (source: keyof DefaultPageStateParams, key: TPageStateKeys[number], value: string) => void,\n]\n\n/**\n * Hook to get default page state as key value pairs from various sources. It provides a convenient abstraction over free form\n * page state like query params by narrowing the used params and centralizing their logic.\n *\n * Future work could include adding support for localStorage, sessionStorage, and precedence of sources.\n * @param defaultPageStateParams various sources of default page state (i.e. queryParams, localStorage, etc.)\n * @returns\n */\nexport const useDefaultPageState = <TQueryParams extends PageStateKeys = PageStateKeys>(\n { queryParams }: DefaultPageStateParams<TQueryParams>,\n): DefaultPageStateReturn<TQueryParams> => {\n const [searchParams, setSearchParams] = useSearchParams()\n\n const patchDefaultPageState = (source: keyof DefaultPageStateParams, key: TQueryParams[number], value: string) => {\n switch (source) {\n case 'queryParams': {\n setSearchParams((prevSearchParams) => {\n const newSearchParams = new URLSearchParams(prevSearchParams)\n newSearchParams.set(key, value)\n return newSearchParams\n })\n break\n }\n default: {\n throw new Error(`Invalid source for default page state: ${source}`)\n }\n }\n }\n\n const queryParamsState = useMemo(() => {\n if (!queryParams) return {} as Record<TQueryParams[number], string>\n let defaultState = {} as Record<TQueryParams[number], string>\n for (const [key, value] of searchParams.entries()) {\n if (queryParams.includes(key)) {\n defaultState[key as TQueryParams[number]] = value\n }\n }\n return defaultState\n }, [searchParams, queryParams])\n\n return [queryParamsState, patchDefaultPageState]\n}\n","import { useDefaultPageState } from './useDefaultPageState.ts'\n\nexport const UtmQueryParamStrings = {\n utmCampaign: 'utm_campaign',\n utmContent: 'utm_content',\n utmMedium: 'utm_medium',\n utmSource: 'utm_source',\n utmTerm: 'utm_term',\n} as const\n\nexport type UtmQueryParams = typeof UtmQueryParamStrings[keyof typeof UtmQueryParamStrings]\n\n/** Get the default page state for utm values from specific query params */\nexport const useDefaultUtmPageState = () => useDefaultPageState<UtmQueryParams[]>({ queryParams: Object.values(UtmQueryParamStrings) })\n"],"mappings":";;;;AAAA,SAASA,kBAAkB;AAC3B,SAAmBC,iBAAiB;AACpC,SAASC,WAAAA,gBAAe;AACxB,SAASC,mBAAAA,wBAAuB;;;ACFhC,SAASC,aAAa;AACtB,SAASC,kBAAkBC,oCAAoC;AAE/D,IAAMC,qBAAqB;AAE3B,IAAIC;AAMG,IAAMC,sBAAsB,mCAAA;AACjC,MAAID,WAAW;AACb,WAAOA;EACT,OAAO;AACLA,gBAAY,MAAME,iBAAiBC,OAAO;MACxCC,SAAS;MACTC,QAAQ;QACNC,QAAQC;QAA8BC,WAAWT;QAAoBU,MAAM;MAC7E;IACF,CAAA;AACA,WAAOT;EACT;AACF,GAZmC;AAc5B,IAAMU,mBAAmB,mCAAA;AAC9B,QAAMV,aAAY,MAAMC,oBAAAA;AACxB,UAAQ,MAAMD,WAAUW,IAAG,GAAIC,SAASC,KAAAA;AAC1C,GAHgC;;;AC1BhC,SAASC,eAAe;AACxB,SAASC,uBAAuB;AAqBzB,IAAMC,sBAAsB,wBACjC,EAAEC,YAAW,MAAwC;AAErD,QAAM,CAACC,cAAcC,eAAAA,IAAmBC,gBAAAA;AAExC,QAAMC,wBAAwB,wBAACC,QAAsCC,KAA2BC,UAAAA;AAC9F,YAAQF,QAAAA;MACN,KAAK,eAAe;AAClBH,wBAAgB,CAACM,qBAAAA;AACf,gBAAMC,kBAAkB,IAAIC,gBAAgBF,gBAAAA;AAC5CC,0BAAgBE,IAAIL,KAAKC,KAAAA;AACzB,iBAAOE;QACT,CAAA;AACA;MACF;MACA,SAAS;AACP,cAAM,IAAIG,MAAM,0CAA0CP,MAAAA,EAAQ;MACpE;IACF;EACF,GAd8B;AAgB9B,QAAMQ,mBAAmBC,QAAQ,MAAA;AAC/B,QAAI,CAACd,YAAa,QAAO,CAAC;AAC1B,QAAIe,eAAe,CAAC;AACpB,eAAW,CAACT,KAAKC,KAAAA,KAAUN,aAAae,QAAO,GAAI;AACjD,UAAIhB,YAAYiB,SAASX,GAAAA,GAAM;AAC7BS,qBAAaT,GAAAA,IAA+BC;MAC9C;IACF;AACA,WAAOQ;EACT,GAAG;IAACd;IAAcD;GAAY;AAE9B,SAAO;IAACa;IAAkBT;;AAC5B,GAjCmC;;;ACpB5B,IAAMc,uBAAuB;EAClCC,aAAa;EACbC,YAAY;EACZC,WAAW;EACXC,WAAW;EACXC,SAAS;AACX;AAKO,IAAMC,yBAAyB,6BAAMC,oBAAsC;EAAEC,aAAaC,OAAOC,OAAOV,oBAAAA;AAAsB,CAAA,GAA/F;;;AHL/B,IAAMW,wBAAwB,wBAACC,oBAAoB,SAAI;AAC5D,QAAM,CAAC,EACLC,cAAcC,aAAaC,YAAYC,YAAYC,SAAQ,CAC5D,IAAIC,uBAAAA;AACL,QAAM,CAAA,EAAEC,eAAAA,IAAmBC,iBAAAA;AAE3B,QAAM,CAACC,yBAAyBC,KAAAA,IAASC,WAAW,YAAA;AAClD,WAAO,MAAMC,oBAAAA;EACf,GAAG,CAAA,CAAE;AAEL,QAAMC,aAAaC,SAAQ,MAAA;AAEzB,UAAMC,MAAW;MAAEC,QAAQC;IAAU;AAKrC,UAAMC,YAAY;MAChBjB;MAAcC;MAAaC;MAAYC;MAAYC;IACrD;AACA,UAAMc,wBAAwBC,OAAOC,QAAQH,SAAAA,EAAWI,KAAK,CAAC,CAACC,KAAKC,KAAAA,MAAM;AACxE,aAAOD,IAAIE,SAAS,MAAA,KAAWD;IACjC,CAAA;AAEA,QAAIL,uBAAuB;AAEzB,UAAIlB,aAAcc,KAAId,eAAeA;AACrC,UAAIC,YAAaa,KAAIb,cAAcA;AACnC,UAAIC,WAAYY,KAAIZ,aAAaA;AACjC,UAAIC,WAAYW,KAAIX,aAAaA;AACjC,UAAIC,SAAUU,KAAIV,WAAWA;AAE7B,aAAOU;IACT,OAAO;AACL,aAAO;IACT;EACF,GAAG;IAACd;IAAcC;IAAaC;IAAYC;IAAYC;GAAS;AAEhE,QAAM,CAAA,EAAEqB,WAAAA,IAAef,WAAW,YAAA;AAChC,QAAIE,cAAcJ,yBAAyB;AAEzC,YAAMA,wBAAwBkB,OAAO;QAACd;OAAW;AAEjD,UAAIb,mBAAmB;AAErBO,wBAAgB,MAAA;AACd,gBAAMqB,YAAY,IAAIC,gBAAAA;AACtB,qBAAWL,SAASJ,OAAOU,OAAOC,oBAAAA,GAAuB;AACvDH,sBAAUI,OAAOR,KAAAA;UACnB;AACA,iBAAOI;QACT,CAAA;MACF;IACF;EACF,GAAG;IAACnB;IAAyBI;IAAYb;GAAkB;AAE3D,SAAO;IAAEa;IAAYH,OAAOA,SAASgB;EAAY;AACnD,GAzDqC;","names":["usePromise","UtmSchema","useMemo","useSearchParams","isUtm","StorageArchivist","StorageArchivistConfigSchema","STORAGE_NAME_SPACE","archivist","UtmStorageArchivist","StorageArchivist","create","account","config","schema","StorageArchivistConfigSchema","namespace","type","LatestUtmPayload","all","findLast","isUtm","useMemo","useSearchParams","useDefaultPageState","queryParams","searchParams","setSearchParams","useSearchParams","patchDefaultPageState","source","key","value","prevSearchParams","newSearchParams","URLSearchParams","set","Error","queryParamsState","useMemo","defaultState","entries","includes","UtmQueryParamStrings","utmCampaign","utmContent","utmMedium","utmSource","utmTerm","useDefaultUtmPageState","useDefaultPageState","queryParams","Object","values","useCaptureUtmLocation","clearAfterCapture","utm_campaign","utm_content","utm_medium","utm_source","utm_term","useDefaultUtmPageState","setSearchParams","useSearchParams","sessionStorageArchivist","error","usePromise","UtmStorageArchivist","utmPayload","useMemo","utm","schema","UtmSchema","utmParams","foundUpdatedUtmParams","Object","entries","some","key","value","includes","insertError","insert","newParams","URLSearchParams","values","UtmQueryParamStrings","delete"]}
@@ -1,6 +1,6 @@
1
1
  import { type Utm } from '@xyo-network/advertising-payload-plugins';
2
- export declare const useCaptureUtmLocation: () => {
3
- utmPayload: Utm;
2
+ export declare const useCaptureUtmLocation: (clearAfterCapture?: boolean) => {
3
+ utmPayload: Utm | null;
4
4
  error: Error | undefined;
5
5
  };
6
6
  //# sourceMappingURL=useCaptureUtmLocation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useCaptureUtmLocation.d.ts","sourceRoot":"","sources":["../../../../src/utm/hooks/useCaptureUtmLocation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,GAAG,EAAa,MAAM,0CAA0C,CAAA;AAM9E,eAAO,MAAM,qBAAqB;;;CA8BjC,CAAA"}
1
+ {"version":3,"file":"useCaptureUtmLocation.d.ts","sourceRoot":"","sources":["../../../../src/utm/hooks/useCaptureUtmLocation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,GAAG,EAAa,MAAM,0CAA0C,CAAA;AAO9E,eAAO,MAAM,qBAAqB;;;CAyDjC,CAAA"}
@@ -6,5 +6,13 @@ export type DefaultPageStateReturn<TPageStateKeys extends PageStateKeys = PageSt
6
6
  Record<TPageStateKeys[number], string>,
7
7
  (source: keyof DefaultPageStateParams, key: TPageStateKeys[number], value: string) => void
8
8
  ];
9
+ /**
10
+ * Hook to get default page state as key value pairs from various sources. It provides a convenient abstraction over free form
11
+ * page state like query params by narrowing the used params and centralizing their logic.
12
+ *
13
+ * Future work could include adding support for localStorage, sessionStorage, and precedence of sources.
14
+ * @param defaultPageStateParams various sources of default page state (i.e. queryParams, localStorage, etc.)
15
+ * @returns
16
+ */
9
17
  export declare const useDefaultPageState: <TQueryParams extends PageStateKeys = PageStateKeys>({ queryParams }: DefaultPageStateParams<TQueryParams>) => DefaultPageStateReturn<TQueryParams>;
10
18
  //# sourceMappingURL=useDefaultPageState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useDefaultPageState.d.ts","sourceRoot":"","sources":["../../../../src/utm/hooks/useDefaultPageState.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,MAAM,WAAW,sBAAsB,CAAC,YAAY,SAAS,aAAa,GAAG,aAAa;IACxF,WAAW,EAAE,YAAY,CAAA;CAC1B;AAED,MAAM,MAAM,sBAAsB,CAAC,cAAc,SAAS,aAAa,GAAG,aAAa,IAAI;IACzF,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACtC,CAAC,MAAM,EAAE,MAAM,sBAAsB,EAAE,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI;CAC3F,CAAA;AAUD,eAAO,MAAM,mBAAmB,GAAI,YAAY,SAAS,aAAa,mCACnD,sBAAsB,CAAC,YAAY,CAAC,KACpD,sBAAsB,CAAC,YAAY,CA+BrC,CAAA"}
1
+ {"version":3,"file":"useDefaultPageState.d.ts","sourceRoot":"","sources":["../../../../src/utm/hooks/useDefaultPageState.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,MAAM,WAAW,sBAAsB,CAAC,YAAY,SAAS,aAAa,GAAG,aAAa;IACxF,WAAW,EAAE,YAAY,CAAA;CAC1B;AAED,MAAM,MAAM,sBAAsB,CAAC,cAAc,SAAS,aAAa,GAAG,aAAa,IAAI;IACzF,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACtC,CAAC,MAAM,EAAE,MAAM,sBAAsB,EAAE,GAAG,EAAE,cAAc,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI;CAC3F,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,GAAI,YAAY,SAAS,aAAa,mCACnD,sBAAsB,CAAC,YAAY,CAAC,KACpD,sBAAsB,CAAC,YAAY,CA+BrC,CAAA"}
@@ -6,5 +6,6 @@ export declare const UtmQueryParamStrings: {
6
6
  readonly utmTerm: "utm_term";
7
7
  };
8
8
  export type UtmQueryParams = typeof UtmQueryParamStrings[keyof typeof UtmQueryParamStrings];
9
+ /** Get the default page state for utm values from specific query params */
9
10
  export declare const useDefaultUtmPageState: () => import("./useDefaultPageState.ts").DefaultPageStateReturn<UtmQueryParams[]>;
10
11
  //# sourceMappingURL=useDefaultUtmPageState.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useDefaultUtmPageState.d.ts","sourceRoot":"","sources":["../../../../src/utm/hooks/useDefaultUtmPageState.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB;;;;;;CAMvB,CAAA;AAEV,MAAM,MAAM,cAAc,GAAG,OAAO,oBAAoB,CAAC,MAAM,OAAO,oBAAoB,CAAC,CAAA;AAG3F,eAAO,MAAM,sBAAsB,mFAAoG,CAAA"}
1
+ {"version":3,"file":"useDefaultUtmPageState.d.ts","sourceRoot":"","sources":["../../../../src/utm/hooks/useDefaultUtmPageState.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB;;;;;;CAMvB,CAAA;AAEV,MAAM,MAAM,cAAc,GAAG,OAAO,oBAAoB,CAAC,MAAM,OAAO,oBAAoB,CAAC,CAAA;AAE3F,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB,mFAAoG,CAAA"}
@@ -1,5 +1,9 @@
1
1
  import type { Utm } from '@xyo-network/advertising-payload-plugins';
2
2
  import { StorageArchivist, StorageArchivistConfigSchema } from '@xyo-network/archivist-storage';
3
+ /**
4
+ * Find or create a single instance of the UtmStorageArchivist
5
+ * @returns Archivist instance
6
+ */
3
7
  export declare const UtmStorageArchivist: () => Promise<StorageArchivist<import("@xylabs/object").BaseParamsFields & {
4
8
  account?: import("@xyo-network/account-model").AccountInstance | "random";
5
9
  addToResolvers?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"UtmStorageArchivist.d.ts","sourceRoot":"","sources":["../../../../src/utm/lib/UtmStorageArchivist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,0CAA0C,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAA;AAU/F,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;oEAY/B,CAAA;AAED,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,GAAG,GAAG,SAAS,CAGhE,CAAA"}
1
+ {"version":3,"file":"UtmStorageArchivist.d.ts","sourceRoot":"","sources":["../../../../src/utm/lib/UtmStorageArchivist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,0CAA0C,CAAA;AAEnE,OAAO,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAA;AAM/F;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;oEAY/B,CAAA;AAED,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,GAAG,GAAG,SAAS,CAGhE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/react-advertising",
3
- "version": "4.1.6",
3
+ "version": "4.1.8",
4
4
  "description": "Common React library for all XYO projects that use React",
5
5
  "keywords": [
6
6
  "xyo",
@@ -43,15 +43,15 @@
43
43
  "lint-pkg": "npmPkgJsonLint ."
44
44
  },
45
45
  "dependencies": {
46
- "@xylabs/react-promise": "^5.2.2",
46
+ "@xylabs/react-promise": "^5.2.4",
47
47
  "@xyo-network/advertising-payload-plugins": "^3.1.1",
48
- "@xyo-network/archivist-storage": "^3.3.0"
48
+ "@xyo-network/archivist-storage": "^3.3.1"
49
49
  },
50
50
  "devDependencies": {
51
- "@mui/material": "^6.1.4",
51
+ "@mui/material": "^6.1.5",
52
52
  "@storybook/react": "^8.3.6",
53
- "@xylabs/ts-scripts-yarn3": "^4.2.1",
54
- "@xylabs/tsconfig-react": "^4.2.1",
53
+ "@xylabs/ts-scripts-yarn3": "^4.2.3",
54
+ "@xylabs/tsconfig-react": "^4.2.3",
55
55
  "react": "^18.3.1",
56
56
  "react-dom": "^18.3.1",
57
57
  "storybook": "^8.3.6",
@@ -1,11 +1,11 @@
1
- import { Box } from '@mui/material'
1
+ import { Box, Typography } from '@mui/material'
2
2
  import type { Meta, StoryFn } from '@storybook/react'
3
3
  import { usePromise } from '@xylabs/react-promise'
4
4
  import type { PropsWithChildren } from 'react'
5
5
  import React, { useEffect } from 'react'
6
6
  import { BrowserRouter, useSearchParams } from 'react-router-dom'
7
7
 
8
- import { UtmStorageArchivist } from '../lib/index.ts'
8
+ import { LatestUtmPayload, UtmStorageArchivist } from '../lib/index.ts'
9
9
  import { useCaptureUtmLocation } from './useCaptureUtmLocation.ts'
10
10
 
11
11
  export default { title: 'advertising/UseCaptureUtmLocation' } as Meta
@@ -14,6 +14,10 @@ const UtmStub: React.FC<PropsWithChildren> = ({ children }) => {
14
14
  const [, setParams] = useSearchParams()
15
15
 
16
16
  useEffect(() => {
17
+ UtmStorageArchivist().then(async (archivist) => {
18
+ await archivist.clear()
19
+ }).catch(error => console.error(error))
20
+
17
21
  setParams(() => {
18
22
  const newParams = new URLSearchParams()
19
23
  newParams.set('utm_campaign', 'test-campaign')
@@ -33,22 +37,47 @@ const RouterDecorator = (Story: StoryFn) => (
33
37
  </BrowserRouter>
34
38
  )
35
39
 
36
- const Template: StoryFn = () => {
37
- useCaptureUtmLocation()
38
-
39
- const [payloads] = usePromise(async () => {
40
- const archivist = await UtmStorageArchivist()
41
- return await archivist.all()
42
- }, [])
40
+ const TemplateInner = ({ message }: { message: string }) => {
41
+ const [params] = useSearchParams()
43
42
 
43
+ const [payload] = usePromise(async () => await LatestUtmPayload(), [])
44
44
  return (
45
- <Box>
46
- {payloads?.map(payload => <Box key={payload.$hash}>{JSON.stringify(payload, null, 2)}</Box>)}
45
+ <Box sx={{
46
+ display: 'flex', flexDirection: 'column', gap: 2,
47
+ }}
48
+ >
49
+ <Typography>
50
+ Stored Payload:
51
+ <code>
52
+ {JSON.stringify(payload, null, 2)}
53
+ </code>
54
+ </Typography>
55
+ <Typography>
56
+ {message}
57
+ <code>
58
+ {JSON.stringify(params.toString(), null, 2)}
59
+ </code>
60
+ </Typography>
47
61
  </Box>
48
62
  )
49
63
  }
50
64
 
65
+ const Template: StoryFn = () => {
66
+ useCaptureUtmLocation()
67
+
68
+ return <TemplateInner message="Query Parameters (should be empty):" />
69
+ }
70
+
71
+ const TemplateWithoutClear: StoryFn = () => {
72
+ useCaptureUtmLocation(false)
73
+
74
+ return <TemplateInner message="Query Parameters (should NOT be empty):" />
75
+ }
76
+
51
77
  const Default = Template.bind({})
52
78
  Default.decorators = [RouterDecorator]
53
79
 
54
- export { Default }
80
+ const WithNoClearAfterCapture = TemplateWithoutClear.bind({})
81
+ WithNoClearAfterCapture.decorators = [RouterDecorator]
82
+
83
+ export { Default, WithNoClearAfterCapture }
@@ -1,14 +1,16 @@
1
1
  import { usePromise } from '@xylabs/react-promise'
2
2
  import { type Utm, UtmSchema } from '@xyo-network/advertising-payload-plugins'
3
3
  import { useMemo } from 'react'
4
+ import { useSearchParams } from 'react-router-dom'
4
5
 
5
6
  import { UtmStorageArchivist } from '../lib/index.ts'
6
- import { useDefaultUtmPageState } from './useDefaultUtmPageState.ts'
7
+ import { useDefaultUtmPageState, UtmQueryParamStrings } from './useDefaultUtmPageState.ts'
7
8
 
8
- export const useCaptureUtmLocation = () => {
9
+ export const useCaptureUtmLocation = (clearAfterCapture = true) => {
9
10
  const [{
10
11
  utm_campaign, utm_content, utm_medium, utm_source, utm_term,
11
12
  }] = useDefaultUtmPageState()
13
+ const [,setSearchParams] = useSearchParams()
12
14
 
13
15
  const [sessionStorageArchivist, error] = usePromise(async () => {
14
16
  return await UtmStorageArchivist()
@@ -18,21 +20,47 @@ export const useCaptureUtmLocation = () => {
18
20
  // Construct the base UTM payload
19
21
  const utm: Utm = { schema: UtmSchema }
20
22
 
21
- // Conditionally add all the UTM parameters present
22
- if (utm_campaign) utm.utm_campaign = utm_campaign
23
- if (utm_content) utm.utm_content = utm_content
24
- if (utm_medium) utm.utm_medium = utm_medium
25
- if (utm_source) utm.utm_source = utm_source
26
- if (utm_term) utm.utm_term = utm_term
23
+ // determine if there's a utm field that still has a value
24
+ // if there is none, it means that either the page loaded
25
+ // with none or they've already been captured
26
+ const utmParams = {
27
+ utm_campaign, utm_content, utm_medium, utm_source, utm_term,
28
+ }
29
+ const foundUpdatedUtmParams = Object.entries(utmParams).some(([key, value]) => {
30
+ return key.includes('utm_') && value
31
+ })
32
+
33
+ if (foundUpdatedUtmParams) {
34
+ // Conditionally add all the UTM parameters present
35
+ if (utm_campaign) utm.utm_campaign = utm_campaign
36
+ if (utm_content) utm.utm_content = utm_content
37
+ if (utm_medium) utm.utm_medium = utm_medium
38
+ if (utm_source) utm.utm_source = utm_source
39
+ if (utm_term) utm.utm_term = utm_term
27
40
 
28
- return utm
41
+ return utm
42
+ } else {
43
+ return null
44
+ }
29
45
  }, [utm_campaign, utm_content, utm_medium, utm_source, utm_term])
30
46
 
31
47
  const [,insertError] = usePromise(async () => {
32
48
  if (utmPayload && sessionStorageArchivist) {
49
+ // insert params into session storage
33
50
  await sessionStorageArchivist.insert([utmPayload])
51
+
52
+ if (clearAfterCapture) {
53
+ // remove the utm params from the URL
54
+ setSearchParams(() => {
55
+ const newParams = new URLSearchParams()
56
+ for (const value of Object.values(UtmQueryParamStrings)) {
57
+ newParams.delete(value)
58
+ }
59
+ return newParams
60
+ })
61
+ }
34
62
  }
35
- }, [sessionStorageArchivist, utmPayload])
63
+ }, [sessionStorageArchivist, utmPayload, clearAfterCapture])
36
64
 
37
65
  return { utmPayload, error: error ?? insertError }
38
66
  }