diff --git a/package.json b/package.json
index 8a657e84..4c38824b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@iterable/web-sdk",
   "description": "Iterable SDK for JavaScript and Node.",
-  "version": "1.1.2",
+  "version": "1.2.0-beta",
   "homepage": "https://iterable.com/",
   "repository": {
     "type": "git",
@@ -74,7 +74,7 @@
     "@types/jest": "^27.0.2",
     "@types/node": "^12.7.1",
     "@types/throttle-debounce": "^2.1.0",
-    "@types/uuid": "^9.0.2",
+    "@types/uuid": "^9.0.8",
     "@typescript-eslint/eslint-plugin": "^5.38.1",
     "@typescript-eslint/parser": "^5.38.1",
     "@webpack-cli/serve": "^1.6.0",
diff --git a/react-example/.eslintrc b/react-example/.eslintrc
index 1583a522..1f749a6a 100644
--- a/react-example/.eslintrc
+++ b/react-example/.eslintrc
@@ -1,13 +1,8 @@
 {
-  "extends": [
-    "../.eslintrc",
-    "plugin:react/recommended"
-  ],
+  "extends": ["../.eslintrc", "plugin:react/recommended"],
   "rules": {
     "@typescript-eslint/no-empty-interface": "off",
-    "react/react-in-jsx-scope": "off",
+    "react/react-in-jsx-scope": "off"
   },
-  "ignorePatterns": [
-    "node_modules/"
-  ]
-}
\ No newline at end of file
+  "ignorePatterns": ["node_modules/"]
+}
diff --git a/react-example/src/components/EventsForm.tsx b/react-example/src/components/EventsForm.tsx
index 7bf6650f..4a113612 100644
--- a/react-example/src/components/EventsForm.tsx
+++ b/react-example/src/components/EventsForm.tsx
@@ -28,10 +28,9 @@ export const EventsForm: FC<Props> = ({
   );
 
   const [trackEvent, setTrackEvent] = useState<string>('');
-
   const [isTrackingEvent, setTrackingEvent] = useState<boolean>(false);
 
-  const handleTrack = (e: FormEvent<HTMLFormElement>) => {
+  const handleTrack = async (e: FormEvent<HTMLFormElement>) => {
     e.preventDefault();
     setTrackingEvent(true);
 
@@ -50,7 +49,6 @@ export const EventsForm: FC<Props> = ({
       })
       .catch((e: any) => {
         setTrackResponse(JSON.stringify(e.response.data));
-        setTrackingEvent(false);
       });
   };
 
diff --git a/react-example/src/components/LoginFormWithoutJWT.tsx b/react-example/src/components/LoginFormWithoutJWT.tsx
new file mode 100644
index 00000000..f1e6c206
--- /dev/null
+++ b/react-example/src/components/LoginFormWithoutJWT.tsx
@@ -0,0 +1,154 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+import { ChangeEvent, FC, FormEvent, useState } from 'react';
+import styled from 'styled-components';
+
+import { IdentityResolution } from '@iterable/web-sdk';
+import { TextField as _TextField } from './TextField';
+import { Button as _Button } from './Button';
+
+import { useUser } from '../context/Users';
+
+const TextField = styled(_TextField)``;
+
+const Button = styled(_Button)`
+  margin-left: 0.4em;
+  max-width: 425px;
+`;
+
+const Form = styled.form`
+  display: flex;
+  flex-flow: row;
+  align-items: center;
+  justify-content: flex-end;
+  height: 100%;
+
+  ${TextField} {
+    align-self: stretch;
+    margin-top: 5px;
+  }
+`;
+
+const StyledDiv = styled.div`
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+`;
+
+const Error = styled.div`
+  color: red;
+`;
+
+interface Props {
+  setEmail: (email: string) => Promise<void>;
+  setUserId: (
+    userId: string,
+    identityResolution?: IdentityResolution
+  ) => Promise<void>;
+  logout: () => void;
+}
+
+export const LoginFormWithoutJWT: FC<Props> = ({
+  setEmail,
+  setUserId,
+  logout
+}) => {
+  const [useEmail, setUseEmail] = useState<boolean>(true);
+  const [user, updateUser] = useState<string>(process.env.LOGIN_EMAIL || '');
+
+  const [error, setError] = useState<string>('');
+
+  const [isEditingUser, setEditingUser] = useState<boolean>(false);
+
+  const { loggedInUser, setLoggedInUser } = useUser();
+
+  const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
+    e.preventDefault();
+
+    const setUser = useEmail ? setEmail : setUserId;
+
+    setUser(user)
+      .then(() => {
+        setEditingUser(false);
+        setLoggedInUser({ type: 'user_update', data: user });
+      })
+      .catch(() => setError('Something went wrong!'));
+  };
+
+  const handleLogout = () => {
+    logout();
+    setLoggedInUser({ type: 'user_update', data: '' });
+  };
+
+  const handleEditUser = () => {
+    updateUser(loggedInUser);
+    setEditingUser(true);
+  };
+
+  const handleCancelEditUser = () => {
+    updateUser('');
+    setEditingUser(false);
+  };
+
+  const handleRadioChange = (e: ChangeEvent<HTMLInputElement>) => {
+    setUseEmail(e.target.value === 'email');
+  };
+
+  const first5 = loggedInUser.substring(0, 5);
+  const last9 = loggedInUser.substring(loggedInUser.length - 9);
+
+  return (
+    <>
+      {loggedInUser && !isEditingUser ? (
+        <>
+          <Button onClick={handleEditUser}>
+            Logged in as {`${first5}...${last9}`} (change)
+          </Button>
+          <Button onClick={handleLogout}>Logout</Button>
+        </>
+      ) : (
+        <StyledDiv>
+          <Form>
+            <div>
+              <input
+                type="radio"
+                id="userId"
+                name="userId"
+                value="userId"
+                checked={!useEmail}
+                onChange={handleRadioChange}
+              />
+              <label>UserId</label>
+            </div>
+            <div>
+              <input
+                type="radio"
+                id="email"
+                name="email"
+                value="email"
+                checked={useEmail}
+                onChange={handleRadioChange}
+              />
+              <label>Email</label>
+            </div>
+          </Form>
+          <Form onSubmit={handleSubmit} data-qa-login-form>
+            <TextField
+              onChange={(e) => updateUser(e.target.value)}
+              value={user}
+              placeholder="e.g. hello@gmail.com"
+              required
+              data-qa-login-input
+            />
+            <Button type="submit">{isEditingUser ? 'Change' : 'Login'}</Button>
+            {isEditingUser && (
+              <Button onClick={handleCancelEditUser}>Cancel</Button>
+            )}
+          </Form>
+          {error && <Error>{error}</Error>}
+        </StyledDiv>
+      )}
+    </>
+  );
+};
+
+export default LoginFormWithoutJWT;
diff --git a/react-example/src/index.tsx b/react-example/src/index.tsx
index 36d698eb..831ec707 100644
--- a/react-example/src/index.tsx
+++ b/react-example/src/index.tsx
@@ -14,6 +14,7 @@ import { EmbeddedMessage } from './views/Embedded';
 import { Link } from './components/Link';
 import { LoginForm } from './components/LoginForm';
 import { EmbeddedMsgs } from './views/EmbeddedMsgs';
+import AUTTesting from './views/AUTTesting';
 
 import { UserProvider } from './context/Users';
 import { EmbeddedMsgsImpressionTracker } from './views/EmbeddedMsgsImpressionTracker';
@@ -45,7 +46,8 @@ const HomeLink = styled(Link)`
     authToken: process.env.API_KEY || '',
     configOptions: {
       isEuIterableService: false,
-      dangerouslyAllowJsPopups: true
+      dangerouslyAllowJsPopups: true,
+      enableAnonActivation: true
     },
     generateJWT: ({ email, userID }) =>
       axios
@@ -65,8 +67,15 @@ const HomeLink = styled(Link)`
         )
         .then((response: any) => response.data?.token)
   };
-  const { setEmail, setUserID, logout, refreshJwtToken } =
-    initializeWithConfig(initializeParams);
+  const {
+    setEmail,
+    setUserID,
+    logout,
+    refreshJwtToken,
+    setVisitorUsageTracked
+  } = initializeWithConfig(initializeParams);
+
+  const handleConsent = (consent?: boolean) => setVisitorUsageTracked(consent);
 
   const container = document.getElementById('root');
   const root = createRoot(container);
@@ -98,6 +107,10 @@ const HomeLink = styled(Link)`
                 path="/embedded-msgs-impression-tracker"
                 element={<EmbeddedMsgsImpressionTracker />}
               />
+              <Route
+                path="/aut-testing"
+                element={<AUTTesting setConsent={handleConsent} />}
+              />
             </Routes>
           </RouteWrapper>
         </UserProvider>
diff --git a/react-example/src/indexWithoutJWT.tsx b/react-example/src/indexWithoutJWT.tsx
new file mode 100644
index 00000000..427ce25d
--- /dev/null
+++ b/react-example/src/indexWithoutJWT.tsx
@@ -0,0 +1,100 @@
+import { initializeWithConfig, WithoutJWTParams } from '@iterable/web-sdk';
+import ReactDOM from 'react-dom';
+import './styles/index.css';
+
+import { BrowserRouter, Routes, Route } from 'react-router-dom';
+import styled from 'styled-components';
+import { Home } from './views/Home';
+import { Commerce } from './views/Commerce';
+import { Events } from './views/Events';
+import { Users } from './views/Users';
+import { InApp } from './views/InApp';
+import LoginFormWithoutJWT from './components/LoginFormWithoutJWT';
+import AUTTesting from './views/AUTTesting';
+import { EmbeddedMsgs } from './views/EmbeddedMsgs';
+import { EmbeddedMessage } from './views/Embedded';
+import { EmbeddedMsgsImpressionTracker } from './views/EmbeddedMsgsImpressionTracker';
+import { Link } from './components/Link';
+import { UserProvider } from './context/Users';
+
+const Wrapper = styled.div`
+  display: flex;
+  flex-flow: column;
+`;
+
+const RouteWrapper = styled.div`
+  width: 90%;
+  margin: 0 auto;
+`;
+
+const HeaderWrapper = styled.div`
+  display: flex;
+  flex-flow: row;
+  align-items: center;
+  justify-content: space-between;
+  margin: 1em;
+`;
+
+const HomeLink = styled(Link)`
+  width: 100px;
+`;
+
+((): void => {
+  // Here we are testing it using NON-JWT based project.
+  const initializeParams: WithoutJWTParams = {
+    authToken: process.env.API_KEY || '',
+    configOptions: {
+      isEuIterableService: false,
+      dangerouslyAllowJsPopups: true,
+      enableAnonActivation: true,
+      onAnonUserCreated: (userId: string) => {
+        console.log('onAnonUserCreated', userId);
+      }
+    }
+  };
+
+  const { setUserID, logout, setEmail, setVisitorUsageTracked } =
+    initializeWithConfig(initializeParams);
+
+  const handleConsent = (consent?: boolean) => setVisitorUsageTracked(consent);
+
+  // eslint-disable-next-line react/no-deprecated
+  ReactDOM.render(
+    <BrowserRouter>
+      <Wrapper>
+        <UserProvider>
+          <HeaderWrapper>
+            <HomeLink renderAsButton to="/">
+              Home
+            </HomeLink>
+            <LoginFormWithoutJWT
+              setEmail={setEmail}
+              setUserId={setUserID}
+              logout={logout}
+            />
+          </HeaderWrapper>
+          <RouteWrapper>
+            <Routes>
+              <Route path="/" element={<Home />} />
+              <Route path="/commerce" element={<Commerce />} />
+              <Route path="/events" element={<Events />} />
+              <Route path="/users" element={<Users />} />
+              <Route path="/inApp" element={<InApp />} />
+              <Route path="/embedded-msgs" element={<EmbeddedMsgs />} />
+              <Route path="/embedded" element={<EmbeddedMessage />} />
+              <Route
+                path="/embedded-msgs-impression-tracker"
+                element={<EmbeddedMsgsImpressionTracker />}
+              />
+              <Route
+                path="/aut-testing"
+                element={<AUTTesting setConsent={handleConsent} />}
+              />
+            </Routes>
+          </RouteWrapper>
+        </UserProvider>
+      </Wrapper>
+    </BrowserRouter>,
+    document.getElementById('root')
+  );
+})();
diff --git a/react-example/src/styles/index.css b/react-example/src/styles/index.css
index 28642755..e6033d05 100644
--- a/react-example/src/styles/index.css
+++ b/react-example/src/styles/index.css
@@ -1,4 +1,5 @@
-html, body {
+html,
+body {
   margin: 0;
   padding: 0;
 }
@@ -30,7 +31,7 @@ html, body {
 }
 
 #change-email-form input {
-  margin-top: .5em;
+  margin-top: 0.5em;
   flex-grow: 1;
   padding: 1em;
 }
@@ -42,17 +43,17 @@ html, body {
     flex-flow: column;
     justify-content: center;
   }
-  
+
   .input-wrapper {
     margin-right: 0;
     transform: translateY(0);
   }
-  
+
   #change-email-form button {
     width: 100%;
     margin-top: 1em;
   }
-  
+
   #change-email-form input {
     height: 50px;
   }
@@ -62,4 +63,34 @@ footer {
   display: flex;
   justify-content: flex-end;
   align-items: flex-end;
-}
\ No newline at end of file
+}
+
+#cookie-consent-container {
+  display: flex;
+  justify-content: center;
+  flex-direction: column;
+
+  position: fixed;
+  bottom: 0;
+  right: 0;
+
+  box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.2);
+  padding: 1em;
+  background: #fff;
+  margin: 1em;
+  max-width: 400px;
+
+  h3 {
+    margin-top: 0;
+    margin-bottom: 0.5em;
+  }
+
+  p {
+    margin-top: 0;
+  }
+
+  div {
+    display: flex;
+    gap: 0.5em;
+  }
+}
diff --git a/react-example/src/views/AUTTesting.tsx b/react-example/src/views/AUTTesting.tsx
new file mode 100644
index 00000000..e0a0ab2c
--- /dev/null
+++ b/react-example/src/views/AUTTesting.tsx
@@ -0,0 +1,304 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable @typescript-eslint/no-unused-vars */
+import { FC, FormEvent, useState } from 'react';
+import {
+  updateCart,
+  trackPurchase,
+  UpdateCartRequestParams,
+  TrackPurchaseRequestParams,
+  updateUser,
+  UpdateUserParams,
+  track,
+  InAppTrackRequestParams
+} from '@iterable/web-sdk';
+import { TextField } from '../components/TextField';
+import {
+  Button,
+  EndpointWrapper,
+  Form,
+  Heading,
+  Response
+} from './Components.styled';
+
+interface Props {
+  setConsent?: (accept: boolean) => void;
+}
+
+export const AUTTesting: FC<Props> = ({ setConsent }) => {
+  const [updateCartResponse, setUpdateCartResponse] = useState<string>(
+    'Endpoint JSON goes here'
+  );
+  const [trackPurchaseResponse, setTrackPurchaseResponse] = useState<string>(
+    'Endpoint JSON goes here'
+  );
+
+  const [cartItem, setCartItem] = useState<string>(
+    '{"items":[{"name":"piano","id":"fdsafds","price":100,"quantity":2}, {"name":"piano2","id":"fdsafds2","price":100,"quantity":5}]}'
+  );
+
+  const [purchaseItem, setPurchaseItem] = useState<string>(
+    '{"items":[{"name":"Black Coffee","id":"fdsafds","price":100,"quantity":2}], "total": 100}'
+  );
+
+  const [isUpdatingCart, setUpdatingCart] = useState<boolean>(false);
+  const [isTrackingPurchase, setTrackingPurchase] = useState<boolean>(false);
+  const [userDataField, setUserDataField] = useState<string>(
+    ' { "dataFields": {"email": "user@example.com","furniture": [{"furnitureType": "Sofa","furnitureColor": "White","lengthInches": 40,"widthInches": 60},{"furnitureType": "Sofa","furnitureColor": "Gray","lengthInches": 20,"widthInches": 30}] }}'
+  );
+  const [isUpdatingUser, setUpdatingUser] = useState<boolean>(false);
+  const [updateUserResponse, setUpdateUserResponse] = useState<string>(
+    'Endpoint JSON goes here'
+  );
+
+  const [trackResponse, setTrackResponse] = useState<string>(
+    'Endpoint JSON goes here'
+  );
+
+  const eventInput =
+    '{"eventName":"button-clicked", "dataFields": {"browserVisit.website.domain":"https://mybrand.com/socks"}}';
+  const [trackEvent, setTrackEvent] = useState<string>(eventInput);
+  const [isTrackingEvent, setTrackingEvent] = useState<boolean>(false);
+
+  const handleParseJson = (isUpdateCartCalled: boolean) => {
+    try {
+      // Parse JSON and assert its type
+      if (isUpdateCartCalled) {
+        const parsedObject = JSON.parse(cartItem) as UpdateCartRequestParams;
+        return parsedObject;
+      }
+      const parsedObject = JSON.parse(
+        purchaseItem
+      ) as TrackPurchaseRequestParams;
+      return parsedObject;
+    } catch (error) {
+      if (isUpdateCartCalled) {
+        setUpdateCartResponse(JSON.stringify(error.message));
+      } else setTrackPurchaseResponse(JSON.stringify(error.message));
+      return error;
+    }
+  };
+
+  const handleParseUserJson = () => {
+    try {
+      // Parse JSON and assert its type
+      return JSON.parse(userDataField) as UpdateUserParams;
+    } catch (error) {
+      setUpdateUserResponse(JSON.stringify(error.message));
+      return error;
+    }
+  };
+
+  const handleUpdateCart = (e: FormEvent<HTMLFormElement>) => {
+    e.preventDefault();
+    const jsonObj: UpdateCartRequestParams = handleParseJson(true);
+    if (jsonObj) {
+      setUpdatingCart(true);
+      try {
+        updateCart(jsonObj)
+          .then((response: any) => {
+            setUpdateCartResponse(JSON.stringify(response.data));
+            setUpdatingCart(false);
+          })
+          .catch((e: any) => {
+            setUpdateCartResponse(JSON.stringify(e));
+            setUpdatingCart(false);
+          });
+      } catch (error) {
+        setUpdateCartResponse(JSON.stringify(error.message));
+        setUpdatingCart(false);
+      }
+    }
+  };
+
+  const handleTrackPurchase = (e: FormEvent<HTMLFormElement>) => {
+    e.preventDefault();
+    const jsonObj: TrackPurchaseRequestParams = handleParseJson(false);
+    if (jsonObj) {
+      setTrackingPurchase(true);
+      try {
+        trackPurchase(jsonObj)
+          .then((response: any) => {
+            setTrackingPurchase(false);
+            setTrackPurchaseResponse(JSON.stringify(response.data));
+          })
+          .catch((e: any) => {
+            setTrackingPurchase(false);
+            setTrackPurchaseResponse(JSON.stringify(e));
+          });
+      } catch (error) {
+        setTrackingPurchase(false);
+        setTrackPurchaseResponse(JSON.stringify(error.message));
+      }
+    }
+  };
+
+  const handleUpdateUser = (e: FormEvent<HTMLFormElement>) => {
+    e.preventDefault();
+    const jsonObj = handleParseUserJson();
+    if (jsonObj) {
+      setUpdatingUser(true);
+      try {
+        updateUser(jsonObj)
+          .then((response: any) => {
+            setUpdateUserResponse(JSON.stringify(response.data));
+            setUpdatingUser(false);
+          })
+          .catch((e: any) => {
+            setUpdateUserResponse(JSON.stringify(e));
+            setUpdatingUser(false);
+          });
+      } catch (error) {
+        setUpdateUserResponse(JSON.stringify(error.message));
+        setUpdatingUser(false);
+      }
+    }
+  };
+
+  const handleParseTrackJson = () => {
+    try {
+      // Parse JSON and assert its type
+      const parsedObject = JSON.parse(trackEvent) as InAppTrackRequestParams;
+      return parsedObject;
+    } catch (error) {
+      setTrackResponse(JSON.stringify(error.message));
+      return error;
+    }
+  };
+
+  const handleTrack = async (e: FormEvent<HTMLFormElement>) => {
+    e.preventDefault();
+    setTrackingEvent(true);
+
+    const jsonObj = handleParseTrackJson();
+    if (jsonObj) {
+      const conditionalParams = jsonObj;
+
+      try {
+        track({
+          ...conditionalParams,
+          deviceInfo: {
+            appPackageName: 'my-website'
+          }
+        })
+          .then((response: any) => {
+            setTrackResponse(JSON.stringify(response.data));
+            setTrackingEvent(false);
+          })
+          .catch((e: any) => {
+            if (e && e.response && e.response.data) {
+              setTrackResponse(JSON.stringify(e.response.data));
+            } else {
+              setTrackResponse(JSON.stringify(e));
+            }
+            setTrackingEvent(false);
+          });
+      } catch (error) {
+        setTrackResponse(JSON.stringify(error.message));
+        setTrackingEvent(false);
+      }
+    }
+  };
+
+  const formAttr = { 'data-qa-track-submit': true };
+  const inputAttr = { 'data-qa-track-input': true };
+  const responseAttr = { 'data-qa-track-response': true };
+
+  const acceptCookie = () => setConsent(true);
+
+  const declineCookie = () => setConsent(false);
+
+  const renderCookieConsent = setConsent && (
+    <div id="cookie-consent-container">
+      <h3>We value your privacy</h3>
+      <p>
+        We use cookies to enhance your browsing experience, serve personalized
+        ads or content, and analyze our traffic. By clicking &quot;Accept&quot;,
+        you consent to our use of cookies.
+      </p>
+      <div>
+        <Button onClick={acceptCookie}>Accept</Button>
+        <Button onClick={declineCookie}>Decline</Button>
+      </div>
+    </div>
+  );
+
+  return (
+    <>
+      <h1>Commerce Endpoints</h1>
+      <Heading>POST /updateCart</Heading>
+      <EndpointWrapper>
+        <Form onSubmit={handleUpdateCart} data-qa-cart-submit>
+          <label htmlFor="item-1">Enter valid JSON</label>
+          <TextField
+            value={cartItem}
+            onChange={(e) => setCartItem(e.target.value)}
+            id="item-1"
+            placeholder='e.g. {"items":[{"name":"piano","id":"fdsafds"}]}'
+            data-qa-cart-input
+          />
+          <Button disabled={isUpdatingCart} type="submit">
+            Submit
+          </Button>
+        </Form>
+        <Response data-qa-cart-response>{updateCartResponse}</Response>
+      </EndpointWrapper>
+      <Heading>POST /trackPurchase</Heading>
+      <EndpointWrapper>
+        <Form onSubmit={handleTrackPurchase} data-qa-purchase-submit>
+          <label htmlFor="item-2">Enter valid JSON</label>
+          <TextField
+            value={purchaseItem}
+            onChange={(e) => setPurchaseItem(e.target.value)}
+            id="item-2"
+            placeholder='e.g. {"items":[{"id":"fdsafds","price":100}]}'
+            data-qa-purchase-input
+          />
+          <Button disabled={isTrackingPurchase} type="submit">
+            Submit
+          </Button>
+        </Form>
+        <Response data-qa-purchase-response>{trackPurchaseResponse}</Response>
+      </EndpointWrapper>
+      <h1>User Endpoint</h1>
+      <Heading>POST /users/update</Heading>
+      <EndpointWrapper>
+        <Form onSubmit={handleUpdateUser} data-qa-update-user-submit>
+          <label htmlFor="item-1">Enter valid JSON here</label>
+          <TextField
+            value={userDataField}
+            onChange={(e) => setUserDataField(e.target.value)}
+            id="item-1"
+            placeholder="e.g. phone_number"
+            data-qa-update-user-input
+            required
+          />
+          <Button disabled={isUpdatingUser} type="submit">
+            Submit
+          </Button>
+        </Form>
+        <Response data-qa-update-user-response>{updateUserResponse}</Response>
+      </EndpointWrapper>
+      <h1>Events Endpoint</h1>
+      <Heading>POST /track</Heading>
+      <EndpointWrapper>
+        <Form onSubmit={handleTrack} {...formAttr}>
+          <label htmlFor="item-1">{'Enter valid JSON'}</label>
+          <TextField
+            value={trackEvent}
+            onChange={(e) => setTrackEvent(e.target.value)}
+            id="item-1"
+            placeholder='e.g. {"eventName":"button-clicked"}'
+            {...inputAttr}
+          />
+          <Button disabled={isTrackingEvent} type="submit">
+            Submit
+          </Button>
+        </Form>
+        <Response {...responseAttr}>{trackResponse}</Response>
+      </EndpointWrapper>
+      {renderCookieConsent}
+    </>
+  );
+};
+
+export default AUTTesting;
diff --git a/react-example/src/views/Commerce.tsx b/react-example/src/views/Commerce.tsx
index f64c281c..74500397 100644
--- a/react-example/src/views/Commerce.tsx
+++ b/react-example/src/views/Commerce.tsx
@@ -28,34 +28,44 @@ export const Commerce: FC<Props> = () => {
   const handleUpdateCart = (e: FormEvent<HTMLFormElement>) => {
     e.preventDefault();
     setUpdatingCart(true);
-    updateCart({
-      items: [{ name: cartItem, id: 'fdsafds', price: 100, quantity: 2 }]
-    })
-      .then((response: any) => {
-        setUpdateCartResponse(JSON.stringify(response.data));
-        setUpdatingCart(false);
+    try {
+      updateCart({
+        items: [{ name: cartItem, id: 'fdsafds', price: 100, quantity: 2 }]
       })
-      .catch((e: any) => {
-        setUpdateCartResponse(JSON.stringify(e.response.data));
-        setUpdatingCart(false);
-      });
+        .then((response: any) => {
+          setUpdateCartResponse(JSON.stringify(response.data));
+          setUpdatingCart(false);
+        })
+        .catch((e: any) => {
+          setUpdateCartResponse(JSON.stringify(e.response.data));
+          setUpdatingCart(false);
+        });
+    } catch (error) {
+      setUpdateCartResponse(JSON.stringify(error.message));
+      setUpdatingCart(false);
+    }
   };
 
   const handleTrackPurchase = (e: FormEvent<HTMLFormElement>) => {
     e.preventDefault();
     setTrackingPurchase(true);
-    trackPurchase({
-      items: [{ name: purchaseItem, id: 'fdsafds', price: 100, quantity: 2 }],
-      total: 200
-    })
-      .then((response: any) => {
-        setTrackingPurchase(false);
-        setTrackPurchaseResponse(JSON.stringify(response.data));
+    try {
+      trackPurchase({
+        items: [{ name: purchaseItem, id: 'fdsafds', price: 100, quantity: 2 }],
+        total: 200
       })
-      .catch((e: any) => {
-        setTrackingPurchase(false);
-        setTrackPurchaseResponse(JSON.stringify(e.response.data));
-      });
+        .then((response: any) => {
+          setTrackingPurchase(false);
+          setTrackPurchaseResponse(JSON.stringify(response.data));
+        })
+        .catch((e: any) => {
+          setTrackingPurchase(false);
+          setTrackPurchaseResponse(JSON.stringify(e.response.data));
+        });
+    } catch (error) {
+      setTrackingPurchase(false);
+      setTrackPurchaseResponse(JSON.stringify(error.message));
+    }
   };
 
   return (
diff --git a/react-example/src/views/Components.styled.ts b/react-example/src/views/Components.styled.ts
index e35d7959..0f2b9e58 100644
--- a/react-example/src/views/Components.styled.ts
+++ b/react-example/src/views/Components.styled.ts
@@ -40,3 +40,5 @@ export const Heading = styled.h2`
 export const StyledButton = styled(Button)`
   margin-top: 1em;
 `;
+
+export { Button };
diff --git a/react-example/src/views/Home.tsx b/react-example/src/views/Home.tsx
index 749a0584..3c4d317c 100644
--- a/react-example/src/views/Home.tsx
+++ b/react-example/src/views/Home.tsx
@@ -41,6 +41,9 @@ export const Home: FC<Props> = () => (
       <StyledLink to="/embedded-msgs-impression-tracker" renderAsButton>
         Embedded msgs impressions tracker
       </StyledLink>
+      <StyledLink to="/aut-testing" renderAsButton>
+        AUT Testing
+      </StyledLink>
     </Wrapper>
   </>
 );
diff --git a/react-example/src/views/Users.tsx b/react-example/src/views/Users.tsx
index 4273d228..df990e36 100644
--- a/react-example/src/views/Users.tsx
+++ b/react-example/src/views/Users.tsx
@@ -40,17 +40,22 @@ export const Users: FC<Props> = () => {
   const handleUpdateUser = (e: FormEvent<HTMLFormElement>) => {
     e.preventDefault();
     setUpdatingUser(true);
-    updateUser({
-      dataFields: { [userDataField]: 'test-data' }
-    })
-      .then((response: any) => {
-        setUpdateUserResponse(JSON.stringify(response.data));
-        setUpdatingUser(false);
+    try {
+      updateUser({
+        dataFields: { [userDataField]: 'test-data' }
       })
-      .catch((e: any) => {
-        setUpdateUserResponse(JSON.stringify(e.response.data));
-        setUpdatingUser(false);
-      });
+        .then((response: any) => {
+          setUpdateUserResponse(JSON.stringify(response.data));
+          setUpdatingUser(false);
+        })
+        .catch((e: any) => {
+          setUpdateUserResponse(JSON.stringify(e.response.data));
+          setUpdatingUser(false);
+        });
+    } catch (error) {
+      setUpdateUserResponse(JSON.stringify(error.message));
+      setUpdatingUser(false);
+    }
   };
 
   const handleUpdateUserEmail = (e: FormEvent<HTMLFormElement>) => {
diff --git a/src/anonymousUserTracking/anonymousUserEventManager.ts b/src/anonymousUserTracking/anonymousUserEventManager.ts
new file mode 100644
index 00000000..497f9684
--- /dev/null
+++ b/src/anonymousUserTracking/anonymousUserEventManager.ts
@@ -0,0 +1,441 @@
+/* eslint-disable class-methods-use-this */
+import { v4 as uuidv4 } from 'uuid';
+import {
+  UpdateCartRequestParams,
+  TrackPurchaseRequestParams
+} from '../commerce/types';
+
+import {
+  GET_CRITERIA_PATH,
+  KEY_EVENT_NAME,
+  KEY_CREATED_AT,
+  KEY_DATA_FIELDS,
+  KEY_CREATE_NEW_FIELDS,
+  SHARED_PREFS_EVENT_TYPE,
+  TRACK_EVENT,
+  SHARED_PREFS_EVENT_LIST_KEY,
+  KEY_ITEMS,
+  KEY_TOTAL,
+  TRACK_PURCHASE,
+  UPDATE_USER,
+  TRACK_UPDATE_CART,
+  SHARED_PREFS_CRITERIA,
+  SHARED_PREFS_ANON_SESSIONS,
+  ENDPOINT_TRACK_ANON_SESSION,
+  WEB_PLATFORM,
+  KEY_PREFER_USERID,
+  ENDPOINTS,
+  DEFAULT_EVENT_THRESHOLD_LIMIT,
+  SHARED_PREF_ANON_USAGE_TRACKED
+} from '../constants';
+import { baseIterableRequest } from '../request';
+import { IterableResponse } from '../types';
+import CriteriaCompletionChecker from './criteriaCompletionChecker';
+import { TrackAnonSessionParams } from '../utils/types';
+import { UpdateUserParams } from '../users/types';
+import { trackSchema } from '../events/events.schema';
+import {
+  trackPurchaseSchema,
+  updateCartSchema
+} from '../commerce/commerce.schema';
+import { updateUserSchema } from '../users/users.schema';
+import { InAppTrackRequestParams } from '../events';
+import config from '../utils/config';
+
+type AnonUserFunction = (userId: string) => void;
+
+let anonUserIdSetter: AnonUserFunction | null = null;
+
+export function registerAnonUserIdSetter(setterFunction: AnonUserFunction) {
+  anonUserIdSetter = setterFunction;
+}
+
+export function isAnonymousUsageTracked(): boolean {
+  const anonymousUsageTracked = localStorage.getItem(
+    SHARED_PREF_ANON_USAGE_TRACKED
+  );
+  return anonymousUsageTracked === 'true';
+}
+
+export class AnonymousUserEventManager {
+  updateAnonSession() {
+    try {
+      const anonymousUsageTracked = isAnonymousUsageTracked();
+
+      if (!anonymousUsageTracked) return;
+
+      const strAnonSessionInfo = localStorage.getItem(
+        SHARED_PREFS_ANON_SESSIONS
+      );
+      let anonSessionInfo: {
+        itbl_anon_sessions?: {
+          number_of_sessions?: number;
+          first_session?: number;
+          last_session?: number;
+        };
+      } = {};
+
+      if (strAnonSessionInfo) {
+        anonSessionInfo = JSON.parse(strAnonSessionInfo);
+      }
+
+      // Update existing values or set them if they don't exist
+      anonSessionInfo.itbl_anon_sessions =
+        anonSessionInfo.itbl_anon_sessions || {};
+      anonSessionInfo.itbl_anon_sessions.number_of_sessions =
+        (anonSessionInfo.itbl_anon_sessions.number_of_sessions || 0) + 1;
+      anonSessionInfo.itbl_anon_sessions.first_session =
+        anonSessionInfo.itbl_anon_sessions.first_session ||
+        this.getCurrentTime();
+      anonSessionInfo.itbl_anon_sessions.last_session = this.getCurrentTime();
+
+      // Update the structure to the desired format
+      const outputObject = {
+        itbl_anon_sessions: anonSessionInfo.itbl_anon_sessions
+      };
+
+      localStorage.setItem(
+        SHARED_PREFS_ANON_SESSIONS,
+        JSON.stringify(outputObject)
+      );
+    } catch (error) {
+      console.error('Error updating anonymous session:', error);
+    }
+  }
+
+  getAnonCriteria() {
+    const anonymousUsageTracked = isAnonymousUsageTracked();
+
+    if (!anonymousUsageTracked) return;
+
+    baseIterableRequest<IterableResponse>({
+      method: 'GET',
+      url: GET_CRITERIA_PATH,
+      data: {},
+      validation: {}
+    })
+      .then((response) => {
+        const criteriaData: any = response.data;
+        if (criteriaData) {
+          localStorage.setItem(
+            SHARED_PREFS_CRITERIA,
+            JSON.stringify(criteriaData)
+          );
+        }
+      })
+      .catch((e) => {
+        console.log('response', e);
+      });
+  }
+
+  async trackAnonEvent(payload: InAppTrackRequestParams) {
+    const newDataObject = {
+      [KEY_EVENT_NAME]: payload.eventName,
+      [KEY_CREATED_AT]: this.getCurrentTime(),
+      [KEY_DATA_FIELDS]: payload.dataFields,
+      [KEY_CREATE_NEW_FIELDS]: true,
+      [SHARED_PREFS_EVENT_TYPE]: TRACK_EVENT
+    };
+    this.storeEventListToLocalStorage(newDataObject, false);
+  }
+
+  async trackAnonUpdateUser(payload: UpdateUserParams) {
+    const newDataObject = {
+      ...payload.dataFields,
+      [SHARED_PREFS_EVENT_TYPE]: UPDATE_USER
+    };
+    this.storeEventListToLocalStorage(newDataObject, true);
+  }
+
+  async trackAnonPurchaseEvent(payload: TrackPurchaseRequestParams) {
+    const newDataObject = {
+      [KEY_ITEMS]: payload.items,
+      [KEY_CREATED_AT]: this.getCurrentTime(),
+      [KEY_DATA_FIELDS]: payload.dataFields,
+      [KEY_TOTAL]: payload.total,
+      [SHARED_PREFS_EVENT_TYPE]: TRACK_PURCHASE
+    };
+    this.storeEventListToLocalStorage(newDataObject, false);
+  }
+
+  async trackAnonUpdateCart(payload: UpdateCartRequestParams) {
+    const newDataObject = {
+      [KEY_ITEMS]: payload.items,
+      [SHARED_PREFS_EVENT_TYPE]: TRACK_UPDATE_CART,
+      [KEY_PREFER_USERID]: true,
+      [KEY_CREATED_AT]: this.getCurrentTime()
+    };
+    this.storeEventListToLocalStorage(newDataObject, false);
+  }
+
+  private checkCriteriaCompletion(): string | null {
+    const criteriaData = localStorage.getItem(SHARED_PREFS_CRITERIA);
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+    try {
+      if (criteriaData && localStoredEventList) {
+        const checker = new CriteriaCompletionChecker(localStoredEventList);
+        return checker.getMatchedCriteria(criteriaData);
+      }
+    } catch (error) {
+      console.error('checkCriteriaCompletion', error);
+    }
+
+    return null;
+  }
+
+  private async createAnonymousUser(criteriaId: string) {
+    const anonymousUsageTracked = isAnonymousUsageTracked();
+
+    if (!anonymousUsageTracked) return;
+
+    const userData = localStorage.getItem(SHARED_PREFS_ANON_SESSIONS);
+    const eventList = localStorage.getItem(SHARED_PREFS_EVENT_LIST_KEY);
+    const events = eventList ? JSON.parse(eventList) : [];
+
+    const dataFields = {
+      ...events.find(
+        (event: any) => event[SHARED_PREFS_EVENT_TYPE] === UPDATE_USER
+      )
+    };
+    delete dataFields[SHARED_PREFS_EVENT_TYPE];
+
+    const userId = uuidv4();
+
+    if (userData) {
+      const userSessionInfo = JSON.parse(userData);
+      const userDataJson = userSessionInfo[SHARED_PREFS_ANON_SESSIONS];
+      const payload: TrackAnonSessionParams = {
+        user: {
+          userId,
+          mergeNestedObjects: true,
+          createNewFields: true,
+          dataFields
+        },
+        createdAt: this.getCurrentTime(),
+        deviceInfo: {
+          appPackageName: window.location.hostname,
+          deviceId: global.navigator.userAgent || '',
+          platform: WEB_PLATFORM
+        },
+        anonSessionContext: {
+          totalAnonSessionCount: userDataJson.number_of_sessions,
+          lastAnonSession: userDataJson.last_session,
+          firstAnonSession: userDataJson.first_session,
+          matchedCriteriaId: parseInt(criteriaId, 10),
+          webPushOptIn:
+            this.getWebPushOptnIn() !== '' ? this.getWebPushOptnIn() : undefined
+        }
+      };
+      const response = await baseIterableRequest<IterableResponse>({
+        method: 'POST',
+        url: ENDPOINT_TRACK_ANON_SESSION,
+        data: payload
+      }).catch((e) => {
+        if (e?.response?.status === 409) {
+          this.getAnonCriteria();
+        }
+      });
+      if (response?.status === 200) {
+        // Update local storage, remove updateUser from local storage
+        localStorage.setItem(
+          SHARED_PREFS_EVENT_LIST_KEY,
+          JSON.stringify(
+            events.filter(
+              (event: any) => event[SHARED_PREFS_EVENT_TYPE] !== UPDATE_USER
+            )
+          )
+        );
+
+        const onAnonUserCreated = config.getConfig('onAnonUserCreated');
+
+        if (onAnonUserCreated) {
+          onAnonUserCreated(userId);
+        }
+        if (anonUserIdSetter !== null) {
+          await anonUserIdSetter(userId);
+        }
+        this.syncEvents();
+      }
+    }
+  }
+
+  async syncEvents() {
+    const strTrackEventList = localStorage.getItem(SHARED_PREFS_EVENT_LIST_KEY);
+    const trackEventList = strTrackEventList
+      ? JSON.parse(strTrackEventList)
+      : [];
+
+    if (trackEventList.length) {
+      trackEventList.forEach(
+        (
+          event: any /* eslint-disable-line @typescript-eslint/no-explicit-any */
+        ) => {
+          const eventType = event[SHARED_PREFS_EVENT_TYPE];
+          // eslint-disable-next-line no-param-reassign
+          delete event.eventType;
+          switch (eventType) {
+            case TRACK_EVENT: {
+              this.track(event);
+              break;
+            }
+            case TRACK_PURCHASE: {
+              this.trackPurchase(event);
+              break;
+            }
+            case TRACK_UPDATE_CART: {
+              this.updateCart(event);
+              break;
+            }
+            case UPDATE_USER: {
+              this.updateUser({ dataFields: event });
+              break;
+            }
+            default:
+              break;
+          }
+          this.removeAnonSessionCriteriaData();
+        }
+      );
+    }
+  }
+
+  removeAnonSessionCriteriaData() {
+    localStorage.removeItem(SHARED_PREFS_ANON_SESSIONS);
+    localStorage.removeItem(SHARED_PREFS_EVENT_LIST_KEY);
+  }
+
+  private async storeEventListToLocalStorage(
+    newDataObject: Record<
+      any /* eslint-disable-line @typescript-eslint/no-explicit-any */,
+      any /* eslint-disable-line @typescript-eslint/no-explicit-any */
+    >,
+    shouldOverWrite: boolean
+  ) {
+    const anonymousUsageTracked = isAnonymousUsageTracked();
+
+    if (!anonymousUsageTracked) return;
+
+    const strTrackEventList = localStorage.getItem(SHARED_PREFS_EVENT_LIST_KEY);
+    let previousDataArray = [];
+
+    if (strTrackEventList) {
+      previousDataArray = JSON.parse(strTrackEventList);
+    }
+
+    if (shouldOverWrite) {
+      const trackingType = newDataObject[SHARED_PREFS_EVENT_TYPE];
+      const indexToUpdate = previousDataArray.findIndex(
+        (obj: any) => obj[SHARED_PREFS_EVENT_TYPE] === trackingType
+      );
+      if (indexToUpdate !== -1) {
+        const dataToUpdate = previousDataArray[indexToUpdate];
+
+        previousDataArray[indexToUpdate] = {
+          ...dataToUpdate,
+          ...newDataObject
+        };
+      } else {
+        previousDataArray.push(newDataObject);
+      }
+    } else {
+      previousDataArray.push(newDataObject);
+    }
+
+    // - The code below limits the number of events stored in local storage.
+    // - The event list acts as a queue, with the oldest events being deleted
+    //   when new events are stored once the event threshold limit is reached.
+
+    const eventThresholdLimit =
+      (config.getConfig('eventThresholdLimit') as number) ??
+      DEFAULT_EVENT_THRESHOLD_LIMIT;
+    if (previousDataArray.length > eventThresholdLimit) {
+      previousDataArray = previousDataArray.slice(
+        previousDataArray.length - eventThresholdLimit
+      );
+    }
+
+    localStorage.setItem(
+      SHARED_PREFS_EVENT_LIST_KEY,
+      JSON.stringify(previousDataArray)
+    );
+    const criteriaId = this.checkCriteriaCompletion();
+    if (criteriaId !== null) {
+      this.createAnonymousUser(criteriaId);
+    }
+  }
+
+  private getCurrentTime = () => {
+    const dateInMillis = new Date().getTime();
+    const dateInSeconds = Math.floor(dateInMillis / 1000);
+    return dateInSeconds;
+  };
+
+  private getWebPushOptnIn(): string {
+    const notificationManager = window.Notification;
+    if (notificationManager && notificationManager.permission === 'granted') {
+      return window.location.hostname;
+    }
+    return '';
+  }
+
+  track = (payload: InAppTrackRequestParams) =>
+    baseIterableRequest<IterableResponse>({
+      method: 'POST',
+      url: ENDPOINTS.event_track.route,
+      data: payload,
+      validation: {
+        data: trackSchema
+      }
+    });
+
+  updateCart = (payload: UpdateCartRequestParams) =>
+    baseIterableRequest<IterableResponse>({
+      method: 'POST',
+      url: ENDPOINTS.commerce_update_cart.route,
+      data: {
+        ...payload,
+        user: {
+          ...payload.user,
+          preferUserId: true
+        }
+      },
+      validation: {
+        data: updateCartSchema
+      }
+    });
+
+  trackPurchase = (payload: TrackPurchaseRequestParams) =>
+    baseIterableRequest<IterableResponse>({
+      method: 'POST',
+      url: ENDPOINTS.commerce_track_purchase.route,
+      data: {
+        ...payload,
+        user: {
+          ...payload.user,
+          preferUserId: true
+        }
+      },
+      validation: {
+        data: trackPurchaseSchema
+      }
+    });
+
+  updateUser = (payload: UpdateUserParams = {}) => {
+    if (payload.dataFields) {
+      return baseIterableRequest<IterableResponse>({
+        method: 'POST',
+        url: ENDPOINTS.users_update.route,
+        data: {
+          ...payload,
+          preferUserId: true
+        },
+        validation: {
+          data: updateUserSchema
+        }
+      });
+    }
+    return null;
+  };
+}
diff --git a/src/anonymousUserTracking/anonymousUserMerge.ts b/src/anonymousUserTracking/anonymousUserMerge.ts
new file mode 100644
index 00000000..0f26f902
--- /dev/null
+++ b/src/anonymousUserTracking/anonymousUserMerge.ts
@@ -0,0 +1,48 @@
+/* eslint-disable class-methods-use-this */
+import { ENDPOINT_MERGE_USER } from '../constants';
+import { baseIterableRequest } from '../request';
+import { IterableResponse } from '../types';
+
+export type MergeApiParams = {
+  sourceEmail: string | null;
+  sourceUserId: string | null;
+  destinationEmail: string | null;
+  destinationUserId: string | null;
+};
+
+export class AnonymousUserMerge {
+  mergeUser(
+    sourceUserId: string | null,
+    sourceEmail: string | null,
+    destinationUserId: string | null,
+    destinationEmail: string | null
+  ): Promise<void> {
+    const mergeApiParams: MergeApiParams = {
+      sourceUserId,
+      sourceEmail,
+      destinationUserId,
+      destinationEmail
+    };
+    return this.callMergeApi(mergeApiParams);
+  }
+
+  private callMergeApi(data: MergeApiParams): Promise<void> {
+    return new Promise((resolve, reject) => {
+      baseIterableRequest<IterableResponse>({
+        method: 'POST',
+        url: ENDPOINT_MERGE_USER,
+        data
+      })
+        .then((response) => {
+          if (response.status === 200) {
+            resolve();
+          } else {
+            reject(new Error(`merge error: ${response.status}`)); // Reject if status is not 200
+          }
+        })
+        .catch((e) => {
+          reject(e); // Reject the promise if the request fails
+        });
+    });
+  }
+}
diff --git a/src/anonymousUserTracking/complexCriteria.test.ts b/src/anonymousUserTracking/complexCriteria.test.ts
new file mode 100644
index 00000000..8d8eb7cd
--- /dev/null
+++ b/src/anonymousUserTracking/complexCriteria.test.ts
@@ -0,0 +1,1217 @@
+import { SHARED_PREFS_EVENT_LIST_KEY } from '../constants';
+import CriteriaCompletionChecker from './criteriaCompletionChecker';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+describe('complexCriteria', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+  });
+
+  // complex criteria
+  it('should return criteriaId 98 (complex criteria 1)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '12',
+                name: 'monitor',
+                price: 50,
+                quantity: 10
+              }
+            ],
+            total: 50,
+            eventType: 'purchase'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Honda',
+              country: 'Japan'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '98',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 23,
+                            value: 'button.clicked'
+                          },
+                          {
+                            field: 'button-clicked.animal',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 25,
+                            value: 'giraffe'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 28,
+                            value: '120'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 29,
+                            valueLong: 100,
+                            value: '100'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 31,
+                            value: 'monitor'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 32,
+                            valueLong: 5,
+                            value: '5'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 34,
+                            value: 'Japan'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 36,
+                            value: 'Honda'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('98');
+  });
+
+  it('should return null (complex criteria 1 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '12',
+                name: 'monitor',
+                price: 50,
+                quantity: 10
+              }
+            ],
+            total: 50,
+            eventType: 'purchase'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Honda'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '98',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 23,
+                            value: 'button.clicked'
+                          },
+                          {
+                            field: 'button-clicked.animal',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 25,
+                            value: 'giraffe'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 28,
+                            value: '120'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 29,
+                            valueLong: 100,
+                            value: '100'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 31,
+                            value: 'monitor'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 32,
+                            valueLong: 5,
+                            value: '5'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 34,
+                            value: 'Japan'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 36,
+                            value: 'Honda'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 99 (complex criteria 2)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Subaru',
+              country: 'USA'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '99',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: 'button-clicked'
+                          },
+                          {
+                            field: 'button-clicked.lastPageViewed',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: 'welcome page'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 2,
+                      maxMatch: 3,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 6,
+                            value: '85'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 7,
+                            valueLong: 50,
+                            value: '50'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 16,
+                            isFiltering: false,
+                            value: 'coffee'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 17,
+                            valueLong: 2,
+                            value: '2'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 19,
+                            value: 'USA'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 21,
+                            value: 'Subaru'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('99');
+  });
+
+  it('should return null (complex criteria 2 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Subaru',
+              country: 'USA'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '99',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: 'button-clicked'
+                          },
+                          {
+                            field: 'button-clicked.lastPageViewed',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: 'welcome page'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 2,
+                      maxMatch: 3,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 6,
+                            value: '85'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 7,
+                            valueLong: 50,
+                            value: '50'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 16,
+                            isFiltering: false,
+                            value: 'coffee'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 17,
+                            valueLong: 2,
+                            value: '2'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 19,
+                            value: 'USA'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 21,
+                            value: 'Subaru'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 100 (complex criteria 3)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+
+          {
+            dataFields: {
+              preferred_car_models: 'Subaru',
+              country: 'USA'
+            },
+            eventType: 'user'
+          },
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              lastPageViewed: 'welcome page'
+            },
+            eventType: 'customEvent'
+          },
+          {
+            items: [
+              {
+                id: '12',
+                name: 'coffee',
+                price: 10,
+                quantity: 5
+              }
+            ],
+            total: 2,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '100',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: 'button-clicked'
+                          },
+                          {
+                            field: 'button-clicked.lastPageViewed',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: 'welcome page'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 2,
+                      maxMatch: 3,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 6,
+                            value: '85'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 7,
+                            valueLong: 50,
+                            value: '50'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 9,
+                            value: 'coffee'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 10,
+                            valueLong: 2,
+                            value: '2'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 12,
+                            value: 'USA'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 14,
+                            value: 'Subaru'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('100');
+  });
+
+  it('should return null (complex criteria 3 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+
+          {
+            dataFields: {
+              preferred_car_models: 'Subaru',
+              country: 'USA'
+            },
+            eventType: 'user'
+          },
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              'button-clicked.lastPageViewed': 'welcome page'
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '100',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: 'button-clicked'
+                          },
+                          {
+                            field: 'button-clicked.lastPageViewed',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: 'welcome page'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 2,
+                      maxMatch: 3,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 6,
+                            value: '85'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 7,
+                            valueLong: 50,
+                            value: '50'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 9,
+                            value: 'coffee'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 10,
+                            valueLong: 2,
+                            value: '2'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 12,
+                            value: 'USA'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 14,
+                            value: 'Subaru'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 101 (complex criteria 4)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              { id: '12', name: 'sneakers', price: 10, quantity: 5 },
+              { id: '13', name: 'slippers', price: 10, quantity: 3 }
+            ],
+            total: 2,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '101',
+            name: 'Complex Criteria 4: (NOT 9) AND 10',
+            createdAt: 1719328083918,
+            updatedAt: 1719328083918,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'sneakers',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'LessThanOrEqualTo',
+                            value: '3',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'slippers',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '3',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('101');
+  });
+
+  it('should return null (complex criteria 4 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              { id: '12', name: 'sneakers', price: 10, quantity: 2 },
+              { id: '13', name: 'slippers', price: 10, quantity: 3 }
+            ],
+            total: 2,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '101',
+            name: 'Complex Criteria 4: (NOT 9) AND 10',
+            createdAt: 1719328083918,
+            updatedAt: 1719328083918,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'sneakers',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'LessThanOrEqualTo',
+                            value: '3',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'slippers',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '3',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+});
diff --git a/src/anonymousUserTracking/criteriaCompletionChecker.ts b/src/anonymousUserTracking/criteriaCompletionChecker.ts
new file mode 100644
index 00000000..82ba844c
--- /dev/null
+++ b/src/anonymousUserTracking/criteriaCompletionChecker.ts
@@ -0,0 +1,610 @@
+/* eslint-disable class-methods-use-this */
+import {
+  SHARED_PREFS_EVENT_TYPE,
+  KEY_ITEMS,
+  TRACK_PURCHASE,
+  TRACK_UPDATE_CART,
+  TRACK_EVENT,
+  UPDATE_CART,
+  UPDATE_USER,
+  KEY_EVENT_NAME,
+  UPDATECART_ITEM_PREFIX,
+  PURCHASE_ITEM_PREFIX,
+  PURCHASE_ITEM
+} from '../constants';
+
+interface SearchQuery {
+  combinator: string;
+  /* eslint-disable-next-line no-use-before-define */
+  searchQueries: SearchQuery[] | Criteria[];
+  dataType?: string;
+  searchCombo?: SearchQuery;
+  field?: string;
+  comparatorType?: string;
+  value?: string;
+  fieldType?: string;
+  minMatch?: number;
+  maxMatch?: number;
+}
+
+interface Criteria {
+  criteriaId: string;
+  name: string;
+  createdAt: number;
+  updatedAt: number;
+  searchQuery: SearchQuery;
+}
+
+class CriteriaCompletionChecker {
+  private localStoredEventList: any[];
+
+  constructor(localStoredEventList: string) {
+    this.localStoredEventList = JSON.parse(localStoredEventList);
+  }
+
+  public getMatchedCriteria(criteriaData: string): string | null {
+    let criteriaId: string | null = null;
+
+    try {
+      const json = JSON.parse(criteriaData);
+      if (json.criteriaSets) {
+        criteriaId = this.findMatchedCriteria(json.criteriaSets);
+      }
+    } catch (e) {
+      this.handleJSONException(e);
+    }
+
+    return criteriaId;
+  }
+
+  private findMatchedCriteria(criteriaList: Criteria[]): string | null {
+    const eventsToProcess = this.prepareEventsToProcess();
+
+    // Use find to get the first matching criteria
+    const matchingCriteria = criteriaList.find((criteria) => {
+      if (criteria.searchQuery && criteria.criteriaId) {
+        return this.evaluateTree(criteria.searchQuery, eventsToProcess);
+      }
+      return false;
+    });
+
+    // Return the criteriaId of the matching criteria or null if none found
+    return matchingCriteria ? matchingCriteria.criteriaId : null;
+  }
+
+  private prepareEventsToProcess(): any[] {
+    const eventsToProcess: any[] = this.getEventsWithCartItems();
+    const nonPurchaseEvents: any[] = this.getNonCartEvents();
+
+    nonPurchaseEvents.forEach((event) => {
+      eventsToProcess.push(event);
+    });
+
+    return eventsToProcess;
+  }
+
+  private getEventsWithCartItems(): any[] {
+    const processedEvents: any[] = [];
+
+    this.localStoredEventList.forEach((localEventData) => {
+      if (
+        localEventData[SHARED_PREFS_EVENT_TYPE] &&
+        localEventData[SHARED_PREFS_EVENT_TYPE] === TRACK_PURCHASE
+      ) {
+        const updatedItem: Record<any, any> = {};
+
+        if (localEventData[KEY_ITEMS]) {
+          let items = localEventData[KEY_ITEMS];
+          items = items.map((item: any) => {
+            const updatItem: any = {};
+            Object.keys(item).forEach((key) => {
+              updatItem[`${PURCHASE_ITEM_PREFIX}${key}`] = item[key];
+            });
+            return updatItem;
+          });
+          updatedItem[PURCHASE_ITEM] = items;
+        }
+
+        if (localEventData.dataFields) {
+          Object.keys(localEventData.dataFields).forEach((key) => {
+            updatedItem[key] = localEventData.dataFields[key];
+          });
+        }
+
+        Object.keys(localEventData).forEach((key) => {
+          if (key !== KEY_ITEMS && key !== 'dataFields') {
+            updatedItem[key] = localEventData[key];
+          }
+        });
+        processedEvents.push({
+          ...updatedItem,
+          [SHARED_PREFS_EVENT_TYPE]: TRACK_PURCHASE
+        });
+      } else if (
+        localEventData[SHARED_PREFS_EVENT_TYPE] &&
+        localEventData[SHARED_PREFS_EVENT_TYPE] === TRACK_UPDATE_CART
+      ) {
+        const updatedItem: any = {};
+
+        if (localEventData[KEY_ITEMS]) {
+          let items = localEventData[KEY_ITEMS];
+          items = items.map((item: any) => {
+            const updatItem: any = {};
+            Object.keys(item).forEach((key) => {
+              updatItem[`${UPDATECART_ITEM_PREFIX}${key}`] = item[key];
+            });
+            return updatItem;
+          });
+          updatedItem[KEY_ITEMS] = items;
+        }
+
+        if (localEventData.dataFields) {
+          Object.keys(localEventData.dataFields).forEach((key) => {
+            updatedItem[key] = localEventData.dataFields[key];
+          });
+          // eslint-disable-next-line no-param-reassign
+          delete localEventData.dataFields;
+        }
+        Object.keys(localEventData).forEach((key) => {
+          if (key !== KEY_ITEMS && key !== 'dataFields') {
+            if (key === SHARED_PREFS_EVENT_TYPE) {
+              updatedItem[key] = TRACK_EVENT;
+            } else {
+              updatedItem[key] = localEventData[key];
+            }
+          }
+        });
+        processedEvents.push({
+          ...updatedItem,
+          [KEY_EVENT_NAME]: UPDATE_CART,
+          [SHARED_PREFS_EVENT_TYPE]: TRACK_EVENT
+        });
+      }
+    });
+    return processedEvents;
+  }
+
+  private getNonCartEvents(): any[] {
+    const nonPurchaseEvents: any[] = [];
+    this.localStoredEventList.forEach((localEventData) => {
+      if (
+        localEventData[SHARED_PREFS_EVENT_TYPE] &&
+        (localEventData[SHARED_PREFS_EVENT_TYPE] === UPDATE_USER ||
+          localEventData[SHARED_PREFS_EVENT_TYPE] === TRACK_EVENT)
+      ) {
+        const updatedItem: any = localEventData;
+        if (localEventData.dataFields) {
+          Object.keys(localEventData.dataFields).forEach((key) => {
+            updatedItem[key] = localEventData.dataFields[key];
+          });
+          // eslint-disable-next-line no-param-reassign
+          delete localEventData.dataFields;
+        }
+        nonPurchaseEvents.push(updatedItem);
+      }
+    });
+    return nonPurchaseEvents;
+  }
+
+  private evaluateTree(
+    node: SearchQuery | Criteria,
+    localEventData: any[]
+  ): boolean {
+    try {
+      if ((node as SearchQuery).searchQueries) {
+        const { combinator } = node as SearchQuery;
+        const { searchQueries } = node as SearchQuery;
+        if (combinator === 'And') {
+          /* eslint-disable-next-line @typescript-eslint/prefer-for-of */
+          for (let i = 0; i < searchQueries.length; i += 1) {
+            if (!this.evaluateTree(searchQueries[i], localEventData)) {
+              return false;
+            }
+          }
+          return true;
+        }
+        if (combinator === 'Or') {
+          /* eslint-disable-next-line @typescript-eslint/prefer-for-of */
+          for (let i = 0; i < searchQueries.length; i += 1) {
+            if (this.evaluateTree(searchQueries[i], localEventData)) {
+              return true;
+            }
+          }
+          return false;
+        }
+        if (combinator === 'Not') {
+          /* eslint-disable-next-line @typescript-eslint/prefer-for-of */
+          for (let i = 0; i < searchQueries.length; i += 1) {
+            (searchQueries[i] as any).isNot = true;
+            if (this.evaluateTree(searchQueries[i], localEventData)) {
+              return false;
+            }
+          }
+          return true;
+        }
+      } else if ((node as SearchQuery).searchCombo) {
+        return this.evaluateSearchQueries(node as SearchQuery, localEventData);
+      }
+    } catch (e) {
+      this.handleException(e);
+    }
+    return false;
+  }
+
+  /* eslint-disable no-continue */
+  private evaluateSearchQueries(
+    node: SearchQuery,
+    localEventData: any[]
+  ): boolean {
+    // this function will compare the actualy searhqueues under search combo
+    for (let i = 0; i < localEventData.length; i += 1) {
+      const eventData = localEventData[i];
+      const trackingType = eventData[SHARED_PREFS_EVENT_TYPE];
+      const { dataType } = node;
+      if (dataType === trackingType) {
+        const { searchCombo } = node;
+        const searchQueries = searchCombo?.searchQueries || [];
+        const combinator = searchCombo?.combinator || '';
+        const isNot = Object.prototype.hasOwnProperty.call(node, 'isNot');
+        if (this.evaluateEvent(eventData, searchQueries, combinator)) {
+          if (node.minMatch) {
+            const minMatch = node.minMatch - 1;
+            // eslint-disable-next-line no-param-reassign
+            node.minMatch = minMatch;
+            if (minMatch > 0) {
+              continue;
+            }
+          }
+          if (isNot && !(i + 1 === localEventData.length)) {
+            continue;
+          }
+          return true;
+        }
+        if (isNot) {
+          return false;
+        }
+      }
+    }
+    return false;
+  }
+
+  private evaluateEvent(
+    localEvent: any,
+    searchQueries: any,
+    combinator: string
+  ): boolean {
+    if (combinator === 'And' || combinator === 'Or') {
+      return this.evaluateFieldLogic(searchQueries, localEvent);
+    }
+    if (combinator === 'Not') {
+      return !this.evaluateFieldLogic(searchQueries, localEvent);
+    }
+    return false;
+  }
+
+  private doesItemCriteriaExists(searchQueries: any[]): boolean {
+    const foundIndex = searchQueries.findIndex(
+      (item) =>
+        item.field.startsWith(UPDATECART_ITEM_PREFIX) ||
+        item.field.startsWith(PURCHASE_ITEM_PREFIX)
+    );
+    return foundIndex !== -1;
+  }
+
+  private evaluateFieldLogic(searchQueries: any[], eventData: any): boolean {
+    const localDataKeys = Object.keys(eventData);
+    let itemMatchedResult = false;
+    let keyItem = null;
+    if (localDataKeys.includes(KEY_ITEMS)) {
+      keyItem = KEY_ITEMS;
+    } else if (localDataKeys.includes(PURCHASE_ITEM)) {
+      keyItem = PURCHASE_ITEM;
+    }
+
+    if (keyItem !== null) {
+      // scenario of items inside purchase and updateCart Events
+      const items = eventData[keyItem];
+      const result = items.some((item: any) =>
+        this.doesItemMatchQueries(item, searchQueries)
+      );
+      if (!result && this.doesItemCriteriaExists(searchQueries)) {
+        // items criteria existed and it did not match
+        return result;
+      }
+      itemMatchedResult = result;
+    }
+    const filteredLocalDataKeys = localDataKeys.filter(
+      (item: any) => item !== KEY_ITEMS
+    );
+
+    if (filteredLocalDataKeys.length === 0) {
+      return itemMatchedResult;
+    }
+
+    const filteredSearchQueries = searchQueries.filter(
+      (searchQuery) =>
+        !searchQuery.field.startsWith(UPDATECART_ITEM_PREFIX) &&
+        !searchQuery.field.startsWith(PURCHASE_ITEM_PREFIX)
+    );
+    if (filteredSearchQueries.length === 0) {
+      return itemMatchedResult;
+    }
+    const matchResult = filteredSearchQueries.every((query: any) => {
+      const { field } = query;
+      if (
+        query.dataType === TRACK_EVENT &&
+        query.fieldType === 'object' &&
+        query.comparatorType === 'IsSet'
+      ) {
+        const eventName = eventData[KEY_EVENT_NAME];
+        if (eventName === UPDATE_CART && field === eventName) {
+          return true;
+        }
+        if (field === eventName) {
+          return true;
+        }
+      }
+
+      const eventKeyItems = filteredLocalDataKeys.filter(
+        (keyItem) => keyItem === field
+      );
+
+      if (field.includes('.')) {
+        const splitField = field.split('.') as string[];
+        const fields =
+          eventData?.eventType === TRACK_EVENT &&
+          eventData?.eventName === splitField[0]
+            ? splitField.slice(1)
+            : splitField;
+
+        let fieldValue = eventData;
+        let isSubFieldArray = false;
+        let isSubMatch = false;
+
+        fields.forEach((subField) => {
+          const subFieldValue = fieldValue[subField];
+          if (
+            Array.isArray(subFieldValue) &&
+            subFieldValue?.[0] instanceof Object
+          ) {
+            isSubFieldArray = true;
+            isSubMatch = subFieldValue.some((item: any) => {
+              const data = fields.reduceRight((acc: any, key) => {
+                if (key === subField) {
+                  return { [key]: item };
+                }
+                return { [key]: acc };
+              }, {});
+
+              return this.evaluateFieldLogic(searchQueries, {
+                ...eventData,
+                ...data
+              });
+            });
+          } else if (subFieldValue instanceof Object) {
+            fieldValue = subFieldValue;
+          }
+        });
+
+        if (isSubFieldArray) {
+          return isSubMatch;
+        }
+
+        const valueFromObj = this.getFieldValue(eventData, field);
+        if (valueFromObj) {
+          return this.evaluateComparison(
+            query.comparatorType,
+            valueFromObj,
+            query.value ?? query.values ?? ''
+          );
+        }
+      } else if (eventKeyItems.length) {
+        return this.evaluateComparison(
+          query.comparatorType,
+          eventData[field],
+          query.value ?? query.values ?? ''
+        );
+      }
+      return false;
+    });
+    return matchResult;
+  }
+
+  private getFieldValue(data: any, field: string): any {
+    const fields: string[] = field.split('.');
+    if (data?.eventType === TRACK_EVENT && data?.eventName === fields[0]) {
+      fields.shift();
+    }
+    return fields.reduce(
+      (value, currentField) =>
+        value && value[currentField] !== undefined
+          ? value[currentField]
+          : undefined,
+      data
+    );
+  }
+
+  private doesItemMatchQueries(item: any, searchQueries: any[]): boolean {
+    let shouldReturn = false;
+    const filteredSearchQueries = searchQueries.filter((searchQuery) => {
+      if (
+        searchQuery.field.startsWith(UPDATECART_ITEM_PREFIX) ||
+        searchQuery.field.startsWith(PURCHASE_ITEM_PREFIX)
+      ) {
+        if (!Object.keys(item).includes(searchQuery.field)) {
+          shouldReturn = true;
+          return false;
+        }
+        return true;
+      }
+      return false;
+    });
+    if (filteredSearchQueries.length === 0 || shouldReturn) {
+      return false;
+    }
+    return filteredSearchQueries.every((query: any) => {
+      const { field } = query;
+      if (Object.prototype.hasOwnProperty.call(item, field)) {
+        return this.evaluateComparison(
+          query.comparatorType,
+          item[field],
+          query.value ?? query.values ?? ''
+        );
+      }
+      return false;
+    });
+  }
+
+  private evaluateComparison(
+    comparatorType: string,
+    matchObj: any,
+    valueToCompare: string | string[]
+  ): boolean {
+    if (!valueToCompare && comparatorType !== 'IsSet') {
+      return false;
+    }
+    switch (comparatorType) {
+      case 'Equals':
+        return this.compareValueEquality(matchObj, valueToCompare);
+      case 'DoesNotEqual':
+        return !this.compareValueEquality(matchObj, valueToCompare);
+      case 'IsSet':
+        return this.issetCheck(matchObj);
+      case 'GreaterThan':
+      case 'LessThan':
+      case 'GreaterThanOrEqualTo':
+      case 'LessThanOrEqualTo':
+        return this.compareNumericValues(
+          matchObj,
+          valueToCompare as string,
+          comparatorType
+        );
+      case 'Contains':
+        return this.compareStringContains(matchObj, valueToCompare as string);
+      case 'StartsWith':
+        return this.compareStringStartsWith(matchObj, valueToCompare as string);
+      case 'MatchesRegex':
+        return this.compareWithRegex(matchObj, valueToCompare as string);
+      default:
+        return false;
+    }
+  }
+
+  private compareValueEquality(
+    sourceTo: any,
+    stringValue: string | string[]
+  ): boolean {
+    if (Array.isArray(sourceTo)) {
+      return sourceTo.some((source) =>
+        this.compareValueEquality(source, stringValue)
+      );
+    }
+
+    if (Array.isArray(stringValue)) {
+      return stringValue.some((value) =>
+        this.compareValueEquality(sourceTo, value)
+      );
+    }
+
+    if (
+      (typeof sourceTo === 'number' || typeof sourceTo === 'boolean') &&
+      stringValue !== ''
+    ) {
+      // eslint-disable-next-line no-restricted-globals
+      if (typeof sourceTo === 'number' && !isNaN(parseFloat(stringValue))) {
+        return sourceTo === parseFloat(stringValue);
+      }
+      if (typeof sourceTo === 'boolean') {
+        return sourceTo === (stringValue === 'true');
+      }
+    } else if (typeof sourceTo === 'string') {
+      return sourceTo === stringValue;
+    }
+    return false;
+  }
+
+  private compareNumericValues(
+    sourceTo: any,
+    stringValue: string,
+    compareOperator: string
+  ): boolean {
+    // eslint-disable-next-line no-restricted-globals
+    if (Array.isArray(sourceTo)) {
+      return sourceTo.some((source) =>
+        this.compareNumericValues(source, stringValue, compareOperator)
+      );
+    }
+
+    if (!Number.isNaN(parseFloat(stringValue))) {
+      const sourceNumber = parseFloat(sourceTo);
+      const numericValue = parseFloat(stringValue);
+      switch (compareOperator) {
+        case 'GreaterThan':
+          return sourceNumber > numericValue;
+        case 'LessThan':
+          return sourceNumber < numericValue;
+        case 'GreaterThanOrEqualTo':
+          return sourceNumber >= numericValue;
+        case 'LessThanOrEqualTo':
+          return sourceNumber <= numericValue;
+        default:
+          return false;
+      }
+    }
+    return false;
+  }
+
+  private compareStringContains(sourceTo: any, stringValue: string): boolean {
+    if (Array.isArray(sourceTo)) {
+      return sourceTo.some((source) =>
+        this.compareStringContains(source, stringValue)
+      );
+    }
+    return (
+      (typeof sourceTo === 'string' || typeof sourceTo === 'object') &&
+      sourceTo.includes(stringValue)
+    );
+  }
+
+  private compareStringStartsWith(sourceTo: any, stringValue: string): boolean {
+    if (Array.isArray(sourceTo)) {
+      return sourceTo.some((source) =>
+        this.compareStringStartsWith(source, stringValue)
+      );
+    }
+    return typeof sourceTo === 'string' && sourceTo.startsWith(stringValue);
+  }
+
+  private compareWithRegex(sourceTo: string, pattern: string): boolean {
+    if (Array.isArray(sourceTo)) {
+      return sourceTo.some((source) => this.compareWithRegex(source, pattern));
+    }
+    try {
+      const regexPattern = new RegExp(pattern);
+      return regexPattern.test(sourceTo);
+    } catch (e) {
+      console.error(e);
+      return false;
+    }
+  }
+
+  private issetCheck(matchObj: string | object | any[]): boolean {
+    if (Array.isArray(matchObj)) {
+      return matchObj.length > 0;
+    }
+    if (typeof matchObj === 'object' && matchObj !== null) {
+      return Object.keys(matchObj).length > 0;
+    }
+    return matchObj !== '';
+  }
+
+  private handleException(e: any) {
+    console.error('Exception occurred', e.toString());
+  }
+
+  private handleJSONException(e: any) {
+    console.error('JSONException occurred', e.toString());
+  }
+}
+
+export default CriteriaCompletionChecker;
diff --git a/src/anonymousUserTracking/tests/anonymousUserEventManager.test.ts b/src/anonymousUserTracking/tests/anonymousUserEventManager.test.ts
new file mode 100644
index 00000000..50d60020
--- /dev/null
+++ b/src/anonymousUserTracking/tests/anonymousUserEventManager.test.ts
@@ -0,0 +1,519 @@
+import { AnonymousUserEventManager } from '../anonymousUserEventManager';
+import { baseIterableRequest } from '../../request';
+import {
+  SHARED_PREFS_ANON_SESSIONS,
+  SHARED_PREFS_EVENT_LIST_KEY,
+  SHARED_PREFS_CRITERIA,
+  SHARED_PREF_ANON_USAGE_TRACKED
+} from '../../constants';
+import { UpdateUserParams } from '../../users';
+import { TrackPurchaseRequestParams } from '../../commerce';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+jest.mock('../criteriaCompletionChecker', () =>
+  jest.fn().mockImplementation(() => ({
+    getMatchedCriteria: jest.fn()
+  }))
+);
+
+jest.mock('../../request', () => ({
+  baseIterableRequest: jest.fn()
+}));
+
+declare global {
+  function uuidv4(): string;
+  function getEmail(): string;
+  function getUserID(): string;
+  function setUserID(): string;
+}
+
+describe('AnonymousUserEventManager', () => {
+  let anonUserEventManager: AnonymousUserEventManager;
+
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+    anonUserEventManager = new AnonymousUserEventManager();
+  });
+
+  afterEach(() => {
+    jest.clearAllMocks();
+  });
+
+  it('should update anonymous session information correctly', () => {
+    const initialAnonSessionInfo = {
+      itbl_anon_sessions: {
+        number_of_sessions: 1,
+        first_session: 123456789,
+        last_session: expect.any(Number)
+      }
+    };
+
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_ANON_SESSIONS) {
+        return JSON.stringify(initialAnonSessionInfo);
+      }
+      if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+        return 'true';
+      }
+      return null;
+    });
+
+    anonUserEventManager.updateAnonSession();
+
+    expect(localStorageMock.setItem).toHaveBeenCalledWith(
+      SHARED_PREFS_ANON_SESSIONS,
+      expect.stringContaining('itbl_anon_sessions')
+    );
+  });
+
+  it('should set criteria data in localStorage when baseIterableRequest succeeds', async () => {
+    const mockResponse = { data: { criteria: 'mockCriteria' } };
+    (baseIterableRequest as jest.Mock).mockResolvedValueOnce(mockResponse);
+
+    const setItemMock = jest.spyOn(localStorage, 'setItem');
+    await anonUserEventManager.getAnonCriteria();
+
+    expect(setItemMock).toHaveBeenCalledWith(
+      SHARED_PREFS_CRITERIA,
+      '{"criteria":"mockCriteria"}'
+    );
+  });
+
+  it('should create known user and make API request when userData is available', async () => {
+    const userData = {
+      number_of_sessions: 5,
+      last_session: 123456789,
+      first_session: 123456789
+    };
+
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === 'criteria') {
+        return JSON.stringify({
+          count: 1,
+          criteriaSets: [
+            {
+              criteriaId: '6',
+              name: 'EventCriteria',
+              createdAt: 1704754280210,
+              updatedAt: 1704754280210,
+              searchQuery: {
+                combinator: 'Or',
+                searchQueries: [
+                  {
+                    combinator: 'Or',
+                    searchQueries: [
+                      {
+                        dataType: 'purchase',
+                        searchCombo: {
+                          combinator: 'And',
+                          searchQueries: [
+                            {
+                              dataType: 'customEvent',
+                              field: 'eventName',
+                              comparatorType: 'Equals',
+                              value: 'testEvent',
+                              fieldType: 'string'
+                            }
+                          ]
+                        }
+                      }
+                    ]
+                  }
+                ]
+              }
+            }
+          ]
+        });
+      }
+      if (key === SHARED_PREFS_ANON_SESSIONS) {
+        return JSON.stringify(userData);
+      }
+      return null;
+    });
+
+    anonUserEventManager.updateAnonSession();
+  });
+
+  it('should call createAnonymousUser when trackAnonEvent is called', async () => {
+    const payload = {
+      eventName: 'testEvent',
+      eventType: 'customEvent'
+    };
+    const eventData = [
+      {
+        eventName: 'testEvent',
+        createdAt: 1708494757530,
+        dataFields: undefined,
+        createNewFields: true,
+        eventType: 'customEvent'
+      }
+    ];
+
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === 'criteria') {
+        return JSON.stringify({
+          count: 1,
+          criteriaSets: [
+            {
+              criteriaId: '6',
+              name: 'EventCriteria',
+              createdAt: 1704754280210,
+              updatedAt: 1704754280210,
+              searchQuery: {
+                combinator: 'Or',
+                searchQueries: [
+                  {
+                    combinator: 'Or',
+                    searchQueries: [
+                      {
+                        dataType: 'purchase',
+                        searchCombo: {
+                          combinator: 'And',
+                          searchQueries: [
+                            {
+                              dataType: 'customEvent',
+                              field: 'eventName',
+                              comparatorType: 'Equals',
+                              value: 'testEvent',
+                              fieldType: 'string'
+                            }
+                          ]
+                        }
+                      }
+                    ]
+                  }
+                ]
+              }
+            }
+          ]
+        });
+      }
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify(eventData);
+      }
+      return null;
+    });
+    await anonUserEventManager.trackAnonEvent(payload);
+  });
+
+  it('should not call createAnonymousUser when trackAnonEvent is called and criteria does not match', async () => {
+    const payload = {
+      eventName: 'Event'
+    };
+    const eventData = [
+      {
+        eventName: 'Event',
+        createdAt: 1708494757530,
+        dataFields: undefined,
+        createNewFields: true,
+        eventType: 'customEvent'
+      }
+    ];
+
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === 'criteria') {
+        return JSON.stringify({
+          count: 1,
+          criteriaSets: [
+            {
+              criteriaId: '6',
+              name: 'EventCriteria',
+              createdAt: 1704754280210,
+              updatedAt: 1704754280210,
+              searchQuery: {
+                combinator: 'Or',
+                searchQueries: [
+                  {
+                    combinator: 'Or',
+                    searchQueries: [
+                      {
+                        dataType: 'purchase',
+                        searchCombo: {
+                          combinator: 'And',
+                          searchQueries: [
+                            {
+                              dataType: 'customEvent',
+                              field: 'eventName',
+                              comparatorType: 'Equals',
+                              value: 'testEvent',
+                              fieldType: 'string'
+                            }
+                          ]
+                        }
+                      }
+                    ]
+                  }
+                ]
+              }
+            }
+          ]
+        });
+      }
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify(eventData);
+      }
+      return null;
+    });
+    await anonUserEventManager.trackAnonEvent(payload);
+  });
+
+  it('should not call createAnonymousUser when trackAnonEvent is called and criteria not find', async () => {
+    const payload = {
+      eventName: 'Event'
+    };
+    const eventData = [
+      {
+        eventName: 'Event',
+        createdAt: 1708494757530,
+        dataFields: undefined,
+        createNewFields: true,
+        eventType: 'customEvent'
+      }
+    ];
+
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === 'criteria') {
+        return null;
+      }
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify(eventData);
+      }
+      return null;
+    });
+    await anonUserEventManager.trackAnonEvent(payload);
+  });
+
+  it('should call createAnonymousUser when trackAnonUpdateUser is called', async () => {
+    const payload: UpdateUserParams = {
+      dataFields: { country: 'UK' }
+    };
+    const userData = [
+      {
+        userId: 'user',
+        createdAt: 1708494757530,
+        dataFields: undefined,
+        createNewFields: true,
+        eventType: 'updateUser'
+      }
+    ];
+
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === 'criteria') {
+        return JSON.stringify({
+          count: 1,
+          criteriaSets: [
+            {
+              criteriaId: '6',
+              name: 'UpdateUserCriteria',
+              createdAt: 1704754280210,
+              updatedAt: 1704754280210,
+              searchQuery: {
+                combinator: 'Or',
+                searchQueries: [
+                  {
+                    combinator: 'Or',
+                    searchQueries: [
+                      {
+                        dataType: 'updateUser',
+                        searchCombo: {
+                          combinator: 'And',
+                          searchQueries: [
+                            {
+                              dataType: 'updateUser',
+                              field: 'userId',
+                              comparatorType: 'Equals',
+                              value: 'user',
+                              fieldType: 'string'
+                            }
+                          ]
+                        }
+                      }
+                    ]
+                  }
+                ]
+              }
+            }
+          ]
+        });
+      }
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify(userData);
+      }
+      return null;
+    });
+    await anonUserEventManager.trackAnonUpdateUser(payload);
+  });
+
+  it('should call createAnonymousUser when trackAnonPurchaseEvent is called', async () => {
+    const payload: TrackPurchaseRequestParams = {
+      items: [
+        {
+          id: '123',
+          name: 'Black Coffee',
+          quantity: 1,
+          price: 4
+        }
+      ],
+      total: 0
+    };
+    const userData = [
+      {
+        items: [
+          {
+            id: '123',
+            name: 'Black Coffee',
+            quantity: 1,
+            price: 4
+          }
+        ],
+        user: {
+          userId: 'user'
+        },
+        total: 0,
+        eventType: 'purchase'
+      }
+    ];
+
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === 'criteria') {
+        return JSON.stringify({
+          count: 1,
+          criteriaSets: [
+            {
+              criteriaId: '6',
+              name: 'shoppingCartItemsCriteria',
+              createdAt: 1704754280210,
+              updatedAt: 1704754280210,
+              searchQuery: {
+                combinator: 'Or',
+                searchQueries: [
+                  {
+                    combinator: 'Or',
+                    searchQueries: [
+                      {
+                        dataType: 'purchase',
+                        searchCombo: {
+                          combinator: 'And',
+                          searchQueries: [
+                            {
+                              dataType: 'purchase',
+                              field: 'shoppingCartItems.name',
+                              comparatorType: 'Equals',
+                              value: 'Black Coffee',
+                              fieldType: 'string'
+                            },
+                            {
+                              dataType: 'purchase',
+                              field: 'shoppingCartItems.price',
+                              comparatorType: 'GreaterThanOrEqualTo',
+                              value: '4.00',
+                              fieldType: 'double'
+                            }
+                          ]
+                        }
+                      }
+                    ]
+                  }
+                ]
+              }
+            }
+          ]
+        });
+      }
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify(userData);
+      }
+      return null;
+    });
+    await anonUserEventManager.trackAnonPurchaseEvent(payload);
+  });
+
+  it('should call createAnonymousUser when trackAnonUpdateCart is called', async () => {
+    const payload: TrackPurchaseRequestParams = {
+      items: [
+        {
+          id: '123',
+          name: 'Black Coffee',
+          quantity: 2,
+          price: 4
+        }
+      ],
+      total: 0
+    };
+    const userData = [
+      {
+        items: [
+          {
+            id: '123',
+            name: 'Black Coffee',
+            quantity: 1,
+            price: 4
+          }
+        ],
+        user: {
+          userId: 'user'
+        },
+        total: 0,
+        eventType: 'cartUpdate'
+      }
+    ];
+
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === 'criteria') {
+        return JSON.stringify({
+          count: 1,
+          criteriaSets: [
+            {
+              criteriaId: '6',
+              name: 'CartUpdateItemsCriteria',
+              createdAt: 1704754280210,
+              updatedAt: 1704754280210,
+              searchQuery: {
+                combinator: 'Or',
+                searchQueries: [
+                  {
+                    combinator: 'Or',
+                    searchQueries: [
+                      {
+                        dataType: 'cartUpdate',
+                        searchCombo: {
+                          combinator: 'And',
+                          searchQueries: [
+                            {
+                              dataType: 'cartUpdate',
+                              field: 'shoppingCartItems.name',
+                              comparatorType: 'Equals',
+                              value: 'Black Coffee',
+                              fieldType: 'string'
+                            },
+                            {
+                              dataType: 'cartUpdate',
+                              field: 'shoppingCartItems.price',
+                              comparatorType: 'GreaterThanOrEqualTo',
+                              value: '4.00',
+                              fieldType: 'double'
+                            }
+                          ]
+                        }
+                      }
+                    ]
+                  }
+                ]
+              }
+            }
+          ]
+        });
+      }
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify(userData);
+      }
+      return null;
+    });
+    await anonUserEventManager.trackAnonUpdateCart(payload);
+  });
+});
diff --git a/src/anonymousUserTracking/tests/combinationLogicCriteria.test.ts b/src/anonymousUserTracking/tests/combinationLogicCriteria.test.ts
new file mode 100644
index 00000000..17d339bb
--- /dev/null
+++ b/src/anonymousUserTracking/tests/combinationLogicCriteria.test.ts
@@ -0,0 +1,1985 @@
+import { SHARED_PREFS_EVENT_LIST_KEY } from '../../constants';
+import CriteriaCompletionChecker from '../criteriaCompletionChecker';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+describe('CombinationLogicCriteria', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+  });
+
+  it('should return criteriaId 1 if Contact Property AND Custom Event is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { total: 10 },
+            eventType: 'customEvent'
+          },
+          {
+            dataFields: { firstName: 'David' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '1',
+            name: 'Combination Logic - Contact Property AND Custom Event',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'total',
+                            comparatorType: 'Equals',
+                            value: '10',
+                            id: 6,
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('1');
+  });
+
+  it('should return null (combination logic criteria 1 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { total: 10 },
+            eventType: 'customEvent'
+          },
+          {
+            dataFields: { firstName: 'Davidson' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '1',
+            name: 'Combination Logic - Contact Property AND Custom Event',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'total',
+                            comparatorType: 'Equals',
+                            value: '10',
+                            id: 6,
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 2 if Contact Property OR Custom Event is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { total: 10 },
+            eventType: 'customEvent'
+          },
+          {
+            dataFields: { firstName: 'David' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '2',
+            name: 'Combination Logic - Contact Property OR Custom Event',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'total',
+                            comparatorType: 'Equals',
+                            value: '10',
+                            id: 6,
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('2');
+  });
+
+  it('should return null (combination logic criteria 2 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { total: 101 },
+            eventType: 'customEvent'
+          },
+          {
+            dataFields: { firstName: 'Davidson' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '2',
+            name: 'Combination Logic - Contact Property OR Custom Event',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'total',
+                            comparatorType: 'Equals',
+                            value: '10',
+                            id: 6,
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 3 if Contact Property NOR (NOT) Custom Event is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              itesm: [{ name: 'Cofee', id: 'fdsafds', price: 10, quantity: 2 }],
+              total: 10
+            },
+            eventType: 'customEvent'
+          },
+          {
+            dataFields: { firstName: 'Davidson' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '3',
+            name: 'Combination Logic - Contact Property NOR (NOT) Custom Event',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'total',
+                            comparatorType: 'Equals',
+                            value: '10',
+                            id: 6,
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('3');
+  });
+
+  it('should return null (combination logic criteria 3 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { total: 1 },
+            eventType: 'customEvent'
+          },
+          {
+            dataFields: { firstName: 'David' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '3',
+            name: 'Combination Logic - Contact Property NOR (NOT) Custom Event',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'total',
+                            comparatorType: 'Equals',
+                            value: '10',
+                            id: 6,
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 4 if UpdateCart AND Contact Property is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: { firstName: 'David' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '4',
+            name: 'Combination Logic - UpdateCart AND Contact Property',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('4');
+  });
+
+  it('should return null (combination logic criteria 4 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: { firstName: 'Davidson' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '4',
+            name: 'Combination Logic - UpdateCart AND Contact Property',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 5 if UpdateCart OR Contact Property is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: { firstName: 'David' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '5',
+            name: 'Combination Logic - UpdateCart OR Contact Property',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('5');
+  });
+
+  it('should return null (combination logic criteria 5 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: { firstName: 'Davidson' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '5',
+            name: 'Combination Logic - UpdateCart OR Contact Property',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 6 if UpdateCart NOR (NOT) Contact Property is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'boiled', id: 'boiled', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: { firstName: 'Davidson' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'Combination Logic - UpdateCart NOR (NOT) Contact Property',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+  });
+
+  it('should return null (combination logic criteria 6 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: { firstName: 'David' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'Combination Logic - UpdateCart NOR (NOT) Contact Property',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'firstName',
+                            comparatorType: 'Equals',
+                            value: 'David',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 7 if Purchase AND UpdateCart is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          },
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '7',
+            name: 'Combination Logic - Purchase AND UpdateCart',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('7');
+  });
+
+  it('should return null (combination logic criteria 7 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          },
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '7',
+            name: 'Combination Logic - Purchase AND UpdateCart',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 8 if Purchase OR UpdateCart is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          },
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '8',
+            name: 'Combination Logic - Purchase OR UpdateCart',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('8');
+  });
+
+  it('should return null (combination logic criteria 8 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          },
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '8',
+            name: 'Combination Logic - Purchase OR UpdateCart',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 9 if Purchase NOR (NOT) UpdateCart is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'beef', id: 'beef', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          },
+          {
+            items: [{ name: 'boiled', id: 'boiled', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '9',
+            name: 'Combination Logic - Purchase NOR (NOT) UpdateCart',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('9');
+  });
+
+  it('should return null (combination logic criteria 9 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          },
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '9',
+            name: 'Combination Logic - Purchase NOR (NOT) UpdateCart',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'fried',
+                            id: 2,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 10 if Custom Event AND Purchase is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { eventName: 'birthday' },
+            eventType: 'customEvent'
+          },
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '10',
+            name: 'Combination Logic - Custom Event AND Purchase',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'birthday',
+                            id: 16,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('10');
+  });
+
+  it('should return null (combination logic criteria 10 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { eventName: 'anniversary' },
+            eventType: 'customEvent'
+          },
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '10',
+            name: 'Combination Logic - Custom Event AND Purchase',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'birthday',
+                            id: 16,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 11 if Custom Event OR Purchase is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { eventName: 'birthday' },
+            eventType: 'customEvent'
+          }
+          /*  {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          } */
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '11',
+            name: 'Combination Logic - Custom Event OR Purchase',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'birthday',
+                            id: 16,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('11');
+  });
+
+  it('should return null (combination logic criteria 11 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { eventName: 'anniversary' },
+            eventType: 'customEvent'
+          },
+          {
+            items: [{ name: 'fried', id: 'fried', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '11',
+            name: 'Combination Logic - Custom Event OR Purchase',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'birthday',
+                            id: 16,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 12 if Custom Event NOR (NOT) Purchase is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { eventName: 'anniversary' },
+            eventType: 'customEvent'
+          },
+          {
+            items: [{ name: 'beef', id: 'beef', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '12',
+            name: 'Combination Logic - Custom Event NOR (NOT) Purchase',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'birthday',
+                            id: 16,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('12');
+  });
+
+  it('should return null (combination logic criteria 12 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: { eventName: 'birthday' },
+            eventType: 'customEvent'
+          },
+          {
+            items: [{ name: 'chicken', id: 'chicken', price: 10, quantity: 2 }],
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '12',
+            name: 'Combination Logic - Custom Event NOR (NOT) Purchase',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'chicken',
+                            id: 13,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'birthday',
+                            id: 16,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+});
diff --git a/src/anonymousUserTracking/tests/compareArrayDataTypes.test.ts b/src/anonymousUserTracking/tests/compareArrayDataTypes.test.ts
new file mode 100644
index 00000000..9ee0bfc2
--- /dev/null
+++ b/src/anonymousUserTracking/tests/compareArrayDataTypes.test.ts
@@ -0,0 +1,804 @@
+import { SHARED_PREFS_EVENT_LIST_KEY } from '../../constants';
+import CriteriaCompletionChecker from '../criteriaCompletionChecker';
+import {
+  IS_NOT_ONE_OF_CRITERIA,
+  ARRAY_CONTAINS_CRITERIA,
+  ARRAY_DOES_NOT_EQUAL_CRITERIA,
+  ARRAY_EQUAL_CRITERIA,
+  ARRAY_GREATER_THAN_CRITERIA,
+  ARRAY_GREATER_THAN_EQUAL_TO_CRITERIA,
+  ARRAY_LESS_THAN_CRITERIA,
+  ARRAY_LESS_THAN_EQUAL_TO_CRITERIA,
+  ARRAY_MATCHREGEX_CRITERIA,
+  ARRAY_STARTSWITH_CRITERIA,
+  IS_ONE_OF_CRITERIA,
+  CUSTOM_EVENT_SINGLE_PRIMITIVE_CRITERIA
+} from './constants';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+describe('compareArrayDataTypes', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+  });
+
+  // MARK: Equal
+  it('should return criteriaId 285 (compare array Equal)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1996, 1997, 2002, 2020, 2024],
+              score: [10.5, 11.5, 12.5, 13.5, 14.5],
+              timestamp: [
+                1722497422151, 1722500235276, 1722500215276, 1722500225276,
+                1722500245276
+              ]
+            },
+            eventType: 'user'
+          },
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              animal: ['cat', 'dog', 'giraffe']
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_EQUAL_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array Equal - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1996, 1998, 2002, 2020, 2024],
+              score: [12.5, 13.5, 14.5],
+              timestamp: [
+                1722497422151, 1722500235276, 1722500225276, 1722500245276
+              ]
+            },
+            eventType: 'user'
+          },
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              animal: ['cat', 'dog']
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_EQUAL_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: DoesNotEqual
+  it('should return criteriaId 285 (compare array DoesNotEqual)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1996, 1998, 2002, 2020, 2024],
+              score: [12.5, 13.5, 14.5],
+              timestamp: [
+                1722497422151, 1722500235276, 1722500225276, 1722500245276
+              ]
+            },
+            eventType: 'user'
+          },
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              animal: ['cat', 'dog']
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_DOES_NOT_EQUAL_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array DoesNotEqual - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1996, 1997, 2002, 2020, 2024],
+              score: [10.5, 11.5, 12.5, 13.5, 14.5],
+              timestamp: [
+                1722497422151, 1722500235276, 1722500215276, 1722500225276,
+                1722500245276
+              ]
+            },
+            eventType: 'user'
+          },
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              animal: ['cat', 'dog', 'giraffe']
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_DOES_NOT_EQUAL_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: GreaterThan
+  it('should return criteriaId 285 (compare array GreaterThan)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1996, 1998, 2002, 2020, 2024]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_GREATER_THAN_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array GreaterThan - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1990, 1992, 1994, 1997]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_GREATER_THAN_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: LessThan
+  it('should return criteriaId 285 (compare array LessThan)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1990, 1992, 1994, 1996, 1998]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_LESS_THAN_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array LessThan - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1997, 1999, 2002, 2004]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_LESS_THAN_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: GreaterThanOrEqualTo
+  it('should return criteriaId 285 (compare array GreaterThanOrEqualTo)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1997, 1998, 2002, 2020, 2024]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_GREATER_THAN_EQUAL_TO_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array GreaterThanOrEqualTo - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1990, 1992, 1994, 1996]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_GREATER_THAN_EQUAL_TO_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: LessThanOrEqualTo
+  it('should return criteriaId 285 (compare array LessThanOrEqualTo)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1990, 1992, 1994, 1996, 1998]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_LESS_THAN_EQUAL_TO_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array LessThanOrEqualTo - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              milestoneYears: [1998, 1999, 2002, 2004]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_LESS_THAN_EQUAL_TO_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: Contains
+  it('should return criteriaId 285 (compare array Contains)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              addresses: [
+                'New York, US',
+                'San Francisco, US',
+                'San Diego, US',
+                'Los Angeles, US',
+                'Tokyo, JP',
+                'Berlin, DE',
+                'London, GB'
+              ]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_CONTAINS_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array Contains - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              addresses: ['Tokyo, JP', 'Berlin, DE', 'London, GB']
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_CONTAINS_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: StartsWith
+  it('should return criteriaId 285 (compare array StartsWith)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              addresses: [
+                'US, New York',
+                'US, San Francisco',
+                'US, San Diego',
+                'US, Los Angeles',
+                'JP, Tokyo',
+                'DE, Berlin',
+                'GB, London'
+              ]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_STARTSWITH_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array StartsWith - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              addresses: ['JP, Tokyo', 'DE, Berlin', 'GB, London']
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_STARTSWITH_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: MatchesRegex
+  it('should return criteriaId 285 (compare array MatchesRegex)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              addresses: [
+                'US, New York',
+                'US, San Francisco',
+                'US, San Diego',
+                'US, Los Angeles',
+                'JP, Tokyo',
+                'DE, Berlin',
+                'GB, London'
+              ]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_MATCHREGEX_CRITERIA)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId null (compare array MatchesRegex - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              addresses: [
+                'US, New York',
+                'US, San Francisco',
+                'US, San Diego',
+                'US, Los Angeles'
+              ]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(ARRAY_MATCHREGEX_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: IsOneOf
+  it('should return criteriaId 299 (compare array IsOneOf)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              country: 'China',
+              addresses: ['US', 'UK', 'JP', 'DE', 'GB']
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(IS_ONE_OF_CRITERIA)
+    );
+    expect(result).toEqual('299');
+  });
+
+  it('should return criteriaId null (compare array IsOneOf - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              country: 'Korea',
+              addresses: ['US', 'UK']
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(IS_ONE_OF_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  // MARK: IsNotOneOf
+  it('should return criteriaId 299 (compare array IsNotOneOf)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              country: 'Korea',
+              addresses: ['US', 'UK']
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(IS_NOT_ONE_OF_CRITERIA)
+    );
+    expect(result).toEqual('299');
+  });
+
+  it('should return criteriaId null (compare array IsNotOneOf - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              country: 'China',
+              addresses: ['US', 'UK', 'JP', 'DE', 'GB']
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(IS_NOT_ONE_OF_CRITERIA)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 467 (Custom event - single primitive array)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              count: [5, 8, 9]
+            },
+            eventType: 'customEvent',
+            eventName: 'animal_found'
+          }
+        ]);
+      }
+
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(CUSTOM_EVENT_SINGLE_PRIMITIVE_CRITERIA)
+    );
+
+    expect(result).toEqual('467');
+  });
+
+  it('should return criteriaId null (Custom event - single primitive array - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              count: [4, 8, 9]
+            },
+            eventType: 'customEvent',
+            eventName: 'animal_found'
+          }
+        ]);
+      }
+
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(CUSTOM_EVENT_SINGLE_PRIMITIVE_CRITERIA)
+    );
+
+    expect(result).toEqual(null);
+  });
+});
diff --git a/src/anonymousUserTracking/tests/complexCriteria.test.ts b/src/anonymousUserTracking/tests/complexCriteria.test.ts
new file mode 100644
index 00000000..973262eb
--- /dev/null
+++ b/src/anonymousUserTracking/tests/complexCriteria.test.ts
@@ -0,0 +1,1854 @@
+import { SHARED_PREFS_EVENT_LIST_KEY } from '../../constants';
+import CriteriaCompletionChecker from '../criteriaCompletionChecker';
+import {
+  COMPLEX_CRITERIA_1,
+  COMPLEX_CRITERIA_2,
+  COMPLEX_CRITERIA_3
+} from './constants';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+describe('complexCriteria', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+  });
+
+  // complex criteria
+  it('should return criteriaId 98 (complex criteria 1)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '12',
+                name: 'monitor',
+                price: 50,
+                quantity: 10
+              }
+            ],
+            total: 50,
+            eventType: 'purchase'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Honda',
+              country: 'Japan'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '98',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 23,
+                            value: 'button.clicked'
+                          },
+                          {
+                            field: 'button-clicked.animal',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 25,
+                            value: 'giraffe'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 28,
+                            value: '120'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 29,
+                            valueLong: 100,
+                            value: '100'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 31,
+                            value: 'monitor'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 32,
+                            valueLong: 5,
+                            value: '5'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 34,
+                            value: 'Japan'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 36,
+                            value: 'Honda'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('98');
+  });
+
+  it('should return null (complex criteria 1 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '12',
+                name: 'monitor',
+                price: 50,
+                quantity: 10
+              }
+            ],
+            total: 50,
+            eventType: 'purchase'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Honda'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '98',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 23,
+                            value: 'button.clicked'
+                          },
+                          {
+                            field: 'button-clicked.animal',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 25,
+                            value: 'giraffe'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 28,
+                            value: '120'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 29,
+                            valueLong: 100,
+                            value: '100'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 31,
+                            value: 'monitor'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 32,
+                            valueLong: 5,
+                            value: '5'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 34,
+                            value: 'Japan'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 36,
+                            value: 'Honda'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 99 (complex criteria 2)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Subaru',
+              country: 'USA'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '99',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: 'button-clicked'
+                          },
+                          {
+                            field: 'button-clicked.lastPageViewed',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: 'welcome page'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 2,
+                      maxMatch: 3,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 6,
+                            value: '85'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 7,
+                            valueLong: 50,
+                            value: '50'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 16,
+                            isFiltering: false,
+                            value: 'coffee'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 17,
+                            valueLong: 2,
+                            value: '2'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 19,
+                            value: 'USA'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 21,
+                            value: 'Subaru'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('99');
+  });
+
+  it('should return null (complex criteria 2 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Subaru',
+              country: 'USA'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '99',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: 'button-clicked'
+                          },
+                          {
+                            field: 'button-clicked.lastPageViewed',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: 'welcome page'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 2,
+                      maxMatch: 3,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 6,
+                            value: '85'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 7,
+                            valueLong: 50,
+                            value: '50'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 16,
+                            isFiltering: false,
+                            value: 'coffee'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 17,
+                            valueLong: 2,
+                            value: '2'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 19,
+                            value: 'USA'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 21,
+                            value: 'Subaru'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 100 (complex criteria 3)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+
+          {
+            dataFields: {
+              preferred_car_models: 'Subaru',
+              country: 'USA'
+            },
+            eventType: 'user'
+          },
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              lastPageViewed: 'welcome page'
+            },
+            eventType: 'customEvent'
+          },
+          {
+            items: [
+              {
+                id: '12',
+                name: 'coffee',
+                price: 10,
+                quantity: 5
+              }
+            ],
+            total: 2,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '100',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: 'button-clicked'
+                          },
+                          {
+                            field: 'button-clicked.lastPageViewed',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: 'welcome page'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 2,
+                      maxMatch: 3,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 6,
+                            value: '85'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 7,
+                            valueLong: 50,
+                            value: '50'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 9,
+                            value: 'coffee'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 10,
+                            valueLong: 2,
+                            value: '2'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 12,
+                            value: 'USA'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 14,
+                            value: 'Subaru'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('100');
+  });
+
+  it('should return null (complex criteria 3 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+          {
+            items: [{ id: '12', name: 'Mocha', price: 90, quantity: 50 }],
+            total: 50,
+            eventType: 'cartUpdate'
+          },
+
+          {
+            dataFields: {
+              preferred_car_models: 'Subaru',
+              country: 'USA'
+            },
+            eventType: 'user'
+          },
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              'button-clicked.lastPageViewed': 'welcome page'
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '100',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'eventName',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: 'button-clicked'
+                          },
+                          {
+                            field: 'button-clicked.lastPageViewed',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: 'welcome page'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 2,
+                      maxMatch: 3,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 6,
+                            value: '85'
+                          },
+                          {
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'customEvent',
+                            id: 7,
+                            valueLong: 50,
+                            value: '50'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'purchase',
+                            id: 9,
+                            value: 'coffee'
+                          },
+                          {
+                            field: 'shoppingCartItems.quantity',
+                            fieldType: 'long',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            dataType: 'purchase',
+                            id: 10,
+                            valueLong: 2,
+                            value: '2'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 12,
+                            value: 'USA'
+                          },
+                          {
+                            field: 'preferred_car_models',
+                            fieldType: 'string',
+                            comparatorType: 'Contains',
+                            dataType: 'user',
+                            id: 14,
+                            value: 'Subaru'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 101 (complex criteria 4)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              { id: '12', name: 'sneakers', price: 10, quantity: 5 },
+              { id: '13', name: 'slippers', price: 10, quantity: 3 }
+            ],
+            total: 2,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '101',
+            name: 'Complex Criteria 4: (NOT 9) AND 10',
+            createdAt: 1719328083918,
+            updatedAt: 1719328083918,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'sneakers',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'LessThanOrEqualTo',
+                            value: '3',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'slippers',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '3',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('101');
+  });
+
+  it('should return null (complex criteria 4 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              { id: '12', name: 'sneakers', price: 10, quantity: 2 },
+              { id: '13', name: 'slippers', price: 10, quantity: 3 }
+            ],
+            total: 2,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '101',
+            name: 'Complex Criteria 4: (NOT 9) AND 10',
+            createdAt: 1719328083918,
+            updatedAt: 1719328083918,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Not',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'sneakers',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'LessThanOrEqualTo',
+                            value: '3',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'slippers',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '3',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 134 (Min-Max 2)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 50, quantity: 50 }],
+            eventType: 'cartUpdate'
+          },
+          {
+            items: [{ id: '12', name: 'Mocha', price: 50.0, quantity: 50 }],
+            eventType: 'cartUpdate'
+          },
+          {
+            dataFields: {
+              preferred_car_models: 'Honda'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '134',
+            name: 'Min-Max 2',
+            createdAt: 1719336370734,
+            updatedAt: 1719337067199,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'Equals',
+                            value: '50.0',
+                            fieldType: 'double'
+                          }
+                        ]
+                      },
+                      minMatch: 2,
+                      maxMatch: 3
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'preferred_car_models',
+                            comparatorType: 'Equals',
+                            value: 'Honda',
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('134');
+  });
+
+  it('should return criteriaId 151 (sampleTest1)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              'animal-found': {
+                type: 'cat',
+                count: 4
+              }
+            },
+            eventType: 'customEvent'
+          },
+          {
+            items: [{ id: '12', name: 'Caramel', price: 3, quantity: 5 }],
+            total: 2,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '151',
+            name: 'test criteria',
+            createdAt: 1719336370734,
+            updatedAt: 1719337067199,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'animal-found.type',
+                            comparatorType: 'Equals',
+                            value: 'cat',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'animal-found.count',
+                            comparatorType: 'LessThan',
+                            value: '5',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '500',
+                            fieldType: 'double'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'LessThan',
+                            value: '20',
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'Caramel',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '2',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'country',
+                            comparatorType: 'Equals',
+                            value: 'UK',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'user',
+                            field: 'likes_boba',
+                            comparatorType: 'Equals',
+                            value: 'false',
+                            fieldType: 'boolean'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('151');
+  });
+
+  it('should return null (sampleTest1 fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              'animal-found.type': 'dog',
+              'animal-found.count': 4
+            },
+            eventType: 'customEvent'
+          },
+          {
+            items: [{ id: '12', name: 'Caramel', price: 3, quantity: 5 }],
+            total: 2,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '151',
+            name: 'test criteria',
+            createdAt: 1719336370734,
+            updatedAt: 1719337067199,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'animal-found.type',
+                            comparatorType: 'Equals',
+                            value: 'cat',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'animal-found.count',
+                            comparatorType: 'LessThan',
+                            value: '5',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '500',
+                            fieldType: 'double'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'LessThan',
+                            value: '20',
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                },
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'Caramel',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '2',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    },
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'country',
+                            comparatorType: 'Equals',
+                            value: 'UK',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'user',
+                            field: 'likes_boba',
+                            comparatorType: 'Equals',
+                            value: 'false',
+                            fieldType: 'boolean'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  //  MARK: Complex criteria #1
+  it('should return criteriaId 290 if (1 OR 2 OR 3) AND (4 AND 5) AND (6 NOT 7) matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              saved_cars: { color: 'black' },
+              'animal-found': { vaccinated: true },
+              eventName: 'birthday'
+            },
+            eventType: 'customEvent'
+          },
+          {
+            dataFields: { reason: 'testing', total: 30 },
+            eventType: 'purchase'
+          },
+          {
+            dataFields: { firstName: 'Adam' },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(COMPLEX_CRITERIA_1)
+    );
+    expect(result).toEqual('290');
+  });
+
+  it('should return criteriaId null if (1 OR 2 OR 3) AND (4 AND 5) AND (6 NOT 7) - No match', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventType: 'user',
+            dataFields: {
+              firstName: 'Alex'
+            }
+          },
+          {
+            eventType: 'customEvent',
+            eventName: 'saved_cars',
+            dataFields: {
+              color: ''
+            }
+          },
+          {
+            eventType: 'customEvent',
+            eventName: 'animal-found',
+            dataFields: {
+              vaccinated: true
+            }
+          },
+          {
+            eventType: 'purchase',
+            dataFields: {
+              total: 30,
+              reason: 'testing'
+            }
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(COMPLEX_CRITERIA_1)
+    );
+    expect(result).toEqual(null);
+  });
+
+  //  MARK: Complex criteria #2
+  it('should return criteriaId 291 if (6 OR 7) OR (4 AND 5) OR (1 NOT 2 NOT 3) matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventType: 'user',
+            dataFields: {
+              firstName: 'xcode'
+            }
+          },
+          {
+            eventType: 'customEvent',
+            eventName: 'saved_cars',
+            dataFields: {
+              color: 'black'
+            }
+          },
+          {
+            eventType: 'customEvent',
+            eventName: 'animal-found',
+            dataFields: {
+              vaccinated: true
+            }
+          },
+          {
+            eventType: 'purchase',
+            dataFields: {
+              total: 110,
+              reason: 'testing'
+            }
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(COMPLEX_CRITERIA_2)
+    );
+    expect(result).toEqual('291');
+  });
+
+  it('should return criteriaId null if (6 OR 7) OR (4 AND 5) OR (1 NOT 2 NOT 3) - No match', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventType: 'user',
+            dataFields: {
+              firstName: 'Alex'
+            }
+          },
+          {
+            eventType: 'purchase',
+            dataFields: {
+              total: 10,
+              reason: 'null'
+            }
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(COMPLEX_CRITERIA_2)
+    );
+    expect(result).toEqual(null);
+  });
+
+  //  MARK: Complex criteria #3
+  it('should return criteriaId 292 if (1 AND 2) NOR (3 OR 4 OR 5) NOR (6 NOR 7) matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataType: 'user',
+            dataFields: {
+              firstName: 'xcode',
+              lastName: 'ssr'
+            }
+          },
+          {
+            dataType: 'customEvent',
+            eventName: 'animal-found',
+            dataFields: {
+              vaccinated: true,
+              count: 10
+            }
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(COMPLEX_CRITERIA_3)
+    );
+    expect(result).toEqual('292');
+  });
+
+  it('should return criteriaId null if (1 AND 2) NOR (3 OR 4 OR 5) NOR (6 NOR 7) - No match', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventType: 'user',
+            dataFields: {
+              firstName: 'Alex',
+              lastName: 'Aris'
+            }
+          },
+          {
+            eventType: 'customEvent',
+            eventName: 'animal-found',
+            dataFields: {
+              vaccinated: false,
+              count: 4
+            }
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(COMPLEX_CRITERIA_3)
+    );
+    expect(result).toEqual(null);
+  });
+});
diff --git a/src/anonymousUserTracking/tests/constants.ts b/src/anonymousUserTracking/tests/constants.ts
new file mode 100644
index 00000000..6773652a
--- /dev/null
+++ b/src/anonymousUserTracking/tests/constants.ts
@@ -0,0 +1,1682 @@
+// CRITERIA TEST CONSTANTS
+
+export const DATA_TYPE_COMPARATOR_EQUALS = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'eventTimeStamp',
+                      comparatorType: 'Equals',
+                      value: '3',
+                      fieldType: 'long'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'savings',
+                      comparatorType: 'Equals',
+                      value: '19.99',
+                      fieldType: 'double'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'likes_boba',
+                      comparatorType: 'Equals',
+                      value: 'true',
+                      fieldType: 'boolean'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'country',
+                      comparatorType: 'Equals',
+                      value: 'Chaina',
+                      fieldType: 'String'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const DATA_TYPE_COMPARATOR_DOES_NOT_EQUAL = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'eventTimeStamp',
+                      comparatorType: 'DoesNotEqual',
+                      value: '3',
+                      fieldType: 'long'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'savings',
+                      comparatorType: 'DoesNotEqual',
+                      value: '19.99',
+                      fieldType: 'double'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'likes_boba',
+                      comparatorType: 'DoesNotEqual',
+                      value: 'true',
+                      fieldType: 'boolean'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const DATA_TYPE_COMPARATOR_LESS_THAN = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '289',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'eventTimeStamp',
+                      comparatorType: 'LessThan',
+                      value: '15',
+                      fieldType: 'long'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'savings',
+                      comparatorType: 'LessThan',
+                      value: '15',
+                      fieldType: 'double'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const DATA_TYPE_COMPARATOR_LESS_THAN_OR_EQUAL_TO = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '290',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'eventTimeStamp',
+                      comparatorType: 'LessThanOrEqualTo',
+                      value: '17',
+                      fieldType: 'long'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'savings',
+                      comparatorType: 'LessThanOrEqualTo',
+                      value: '17',
+                      fieldType: 'double'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const DATA_TYPE_COMPARATOR_GREATER_THAN = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '290',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'eventTimeStamp',
+                      comparatorType: 'GreaterThan',
+                      value: '50',
+                      fieldType: 'long'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'savings',
+                      comparatorType: 'GreaterThan',
+                      value: '55',
+                      fieldType: 'double'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const DATA_TYPE_COMPARATOR_GREATER_THAN_OR_EQUAL_TO = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '291',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'eventTimeStamp',
+                      comparatorType: 'GreaterThanOrEqualTo',
+                      value: '20',
+                      fieldType: 'long'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'savings',
+                      comparatorType: 'GreaterThanOrEqualTo',
+                      value: '20',
+                      fieldType: 'double'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const DATA_TYPE_COMPARATOR_IS_SET = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'eventTimeStamp',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'long'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'savings',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'double'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'saved_cars',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'double'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'country',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'double'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_EQUAL_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_Array_Equal',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'milestoneYears',
+                      fieldType: 'string',
+                      comparatorType: 'Equals',
+                      dataType: 'user',
+                      id: 2,
+                      value: '1997'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'score',
+                      fieldType: 'double',
+                      comparatorType: 'Equals',
+                      dataType: 'user',
+                      id: 2,
+                      value: '11.5'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'timestamp',
+                      fieldType: 'long',
+                      comparatorType: 'Equals',
+                      dataType: 'user',
+                      id: 2,
+                      valueLong: 1722500215276,
+                      value: '1722500215276'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'button-clicked.animal',
+                      fieldType: 'string',
+                      comparatorType: 'Equals',
+                      dataType: 'customEvent',
+                      id: 25,
+                      value: 'giraffe'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_DOES_NOT_EQUAL_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_Array_DoesNotEqual',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'milestoneYears',
+                      fieldType: 'string',
+                      comparatorType: 'DoesNotEqual',
+                      dataType: 'user',
+                      id: 2,
+                      value: '1997'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'score',
+                      fieldType: 'double',
+                      comparatorType: 'DoesNotEqual',
+                      dataType: 'user',
+                      id: 2,
+                      value: '11.5'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'timestamp',
+                      fieldType: 'long',
+                      comparatorType: 'DoesNotEqual',
+                      dataType: 'user',
+                      id: 2,
+                      valueLong: 1722500215276,
+                      value: '1722500215276'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'button-clicked.animal',
+                      fieldType: 'string',
+                      comparatorType: 'DoesNotEqual',
+                      dataType: 'customEvent',
+                      id: 25,
+                      value: 'giraffe'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_GREATER_THAN_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'milestoneYears',
+                      fieldType: 'string',
+                      comparatorType: 'GreaterThan',
+                      dataType: 'user',
+                      id: 2,
+                      value: '1997'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_LESS_THAN_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'milestoneYears',
+                      fieldType: 'string',
+                      comparatorType: 'LessThan',
+                      dataType: 'user',
+                      id: 2,
+                      value: '1997'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_GREATER_THAN_EQUAL_TO_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'milestoneYears',
+                      fieldType: 'string',
+                      comparatorType: 'GreaterThanOrEqualTo',
+                      dataType: 'user',
+                      id: 2,
+                      value: '1997'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_LESS_THAN_EQUAL_TO_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'milestoneYears',
+                      fieldType: 'string',
+                      comparatorType: 'LessThanOrEqualTo',
+                      dataType: 'user',
+                      id: 2,
+                      value: '1997'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_CONTAINS_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'addresses',
+                      fieldType: 'string',
+                      comparatorType: 'Contains',
+                      dataType: 'user',
+                      id: 2,
+                      value: 'US'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_STARTSWITH_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'addresses',
+                      fieldType: 'string',
+                      comparatorType: 'StartsWith',
+                      dataType: 'user',
+                      id: 2,
+                      value: 'US'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const ARRAY_MATCHREGEX_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '285',
+      name: 'Criteria_EventTimeStamp_3_Long',
+      createdAt: 1722497422151,
+      updatedAt: 1722500235276,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      field: 'addresses',
+                      fieldType: 'string',
+                      comparatorType: 'MatchesRegex',
+                      dataType: 'user',
+                      id: 2,
+                      value: '^(JP|DE|GB)'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const NESTED_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '168',
+      name: 'nested testing',
+      createdAt: 1721251169153,
+      updatedAt: 1723488175352,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'furniture',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'nested'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'furniture.furnitureType',
+                      comparatorType: 'Equals',
+                      value: 'Sofa',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'furniture.furnitureColor',
+                      comparatorType: 'Equals',
+                      value: 'White',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const NESTED_CRITERIA_MULTI_LEVEL = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '425',
+      name: 'Multi level Nested field criteria',
+      createdAt: 1721251169153,
+      updatedAt: 1723488175352,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'button-clicked.browserVisit.website.domain',
+                      comparatorType: 'Equals',
+                      value: 'https://mybrand.com/socks',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const NESTED_CRITERIA_MULTI_LEVEL_ARRAY = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '436',
+      name: 'Criteria 2.1 - 09252024 Bug Bash',
+      createdAt: 1727286807360,
+      updatedAt: 1727445082036,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'furniture.material.type',
+                      comparatorType: 'Contains',
+                      value: 'table',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'furniture.material.color',
+                      comparatorType: 'Equals',
+                      values: ['black']
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const NESTED_CRITERIA_MULTI_LEVEL_ARRAY_TRACK_EVENT = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '459',
+      name: 'event a.h.b=d && a.h.c=g',
+      createdAt: 1721251169153,
+      updatedAt: 1723488175352,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'TopLevelArrayObject.a.h.b',
+                      comparatorType: 'Equals',
+                      value: 'd',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'customEvent',
+                      field: 'TopLevelArrayObject.a.h.c',
+                      comparatorType: 'Equals',
+                      value: 'g',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const IS_ONE_OF_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '299',
+      name: 'Criteria_Is_One_of',
+      createdAt: 1722851586508,
+      updatedAt: 1724404229481,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'country',
+                      comparatorType: 'Equals',
+                      values: ['China', 'Japan', 'Kenya']
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'addresses',
+                      comparatorType: 'Equals',
+                      values: ['JP', 'DE', 'GB']
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const IS_NOT_ONE_OF_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '299',
+      name: 'Criteria_Is_Not_One_of',
+      createdAt: 1722851586508,
+      updatedAt: 1724404229481,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'country',
+                      comparatorType: 'DoesNotEqual',
+                      values: ['China', 'Japan', 'Kenya']
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'addresses',
+                      comparatorType: 'DoesNotEqual',
+                      values: ['JP', 'DE', 'GB']
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const CUSTOM_EVENT_SINGLE_PRIMITIVE_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '467',
+      name: 'Custom event - single primitive',
+      createdAt: 1728166585122,
+      updatedAt: 1729581351423,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'eventName',
+                      comparatorType: 'Equals',
+                      value: 'animal_found',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'customEvent',
+                      field: 'animal_found.count',
+                      comparatorType: 'DoesNotEqual',
+                      value: '4',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const CUSTOM_EVENT_API_TEST_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '6',
+      name: 'EventCriteria',
+      createdAt: 1704754280210,
+      updatedAt: 1704754280210,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'eventName',
+                      comparatorType: 'Equals',
+                      value: 'animal-found',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'customEvent',
+                      field: 'animal-found.type',
+                      comparatorType: 'Equals',
+                      value: 'cat',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'customEvent',
+                      field: 'animal-found.count',
+                      comparatorType: 'Equals',
+                      value: '6',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'customEvent',
+                      field: 'animal-found.vaccinated',
+                      comparatorType: 'Equals',
+                      value: 'true',
+                      fieldType: 'boolean'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const USER_UPDATE_API_TEST_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '6',
+      name: 'UserCriteria',
+      createdAt: 1704754280210,
+      updatedAt: 1704754280210,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'furniture.furnitureType',
+                      comparatorType: 'Equals',
+                      value: 'Sofa',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'user',
+                      field: 'furniture.furnitureColor',
+                      comparatorType: 'Equals',
+                      value: 'White',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const USER_MERGE_SCENARIO_CRITERIA = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '6',
+      name: 'EventCriteria',
+      createdAt: 1704754280210,
+      updatedAt: 1704754280210,
+      searchQuery: {
+        combinator: 'Or',
+        searchQueries: [
+          {
+            combinator: 'Or',
+            searchQueries: [
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'eventName',
+                      comparatorType: 'Equals',
+                      value: 'testEvent',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const NESTED_CRITERIA_MULTI_LEVEL_MORE_THAN_4_EVENTS = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '484',
+      name: 'NickBBFinalUserFlow',
+      createdAt: 1729009617581,
+      updatedAt: 1730096250121,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'likes_boba',
+                      comparatorType: 'Equals',
+                      value: 'true',
+                      fieldType: 'boolean'
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'cancelled_booking.details.event.name',
+                      comparatorType: 'Equals',
+                      value: 'haircut',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+// MARK:Complex Criteria
+
+export const COMPLEX_CRITERIA_1 = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '290',
+      name: 'Complex Criteria Unit Test #1',
+      createdAt: 1722532861551,
+      updatedAt: 1722532861551,
+      searchQuery: {
+        combinator: 'And',
+        searchQueries: [
+          {
+            combinator: 'Or',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'firstName',
+                      comparatorType: 'StartsWith',
+                      value: 'A',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'firstName',
+                      comparatorType: 'StartsWith',
+                      value: 'B',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'firstName',
+                      comparatorType: 'StartsWith',
+                      value: 'C',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'eventName',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'customEvent',
+                      field: 'saved_cars.color',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'eventName',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'customEvent',
+                      field: 'animal-found.vaccinated',
+                      comparatorType: 'Equals',
+                      value: 'true',
+                      fieldType: 'boolean'
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          {
+            combinator: 'Not',
+            searchQueries: [
+              {
+                dataType: 'purchase',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      field: 'total',
+                      comparatorType: 'LessThanOrEqualTo',
+                      value: '100',
+                      fieldType: 'double'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'purchase',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      field: 'reason',
+                      comparatorType: 'Equals',
+                      value: 'null',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const COMPLEX_CRITERIA_2 = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '291',
+      name: 'Complex Criteria Unit Test #2',
+      createdAt: 1722533473263,
+      updatedAt: 1722533473263,
+      searchQuery: {
+        combinator: 'Or',
+        searchQueries: [
+          {
+            combinator: 'Not',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'firstName',
+                      comparatorType: 'StartsWith',
+                      value: 'A',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'firstName',
+                      comparatorType: 'StartsWith',
+                      value: 'B',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'firstName',
+                      comparatorType: 'StartsWith',
+                      value: 'C',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'eventName',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'string'
+                    },
+                    {
+                      dataType: 'customEvent',
+                      field: 'saved_cars.color',
+                      comparatorType: 'IsSet',
+                      value: '',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'animal-found.vaccinated',
+                      comparatorType: 'Equals',
+                      value: 'true',
+                      fieldType: 'boolean'
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          {
+            combinator: 'Or',
+            searchQueries: [
+              {
+                dataType: 'purchase',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      field: 'total',
+                      comparatorType: 'GreaterThanOrEqualTo',
+                      value: '100',
+                      fieldType: 'double'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'purchase',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      field: 'reason',
+                      comparatorType: 'DoesNotEqual',
+                      value: 'null',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
+
+export const COMPLEX_CRITERIA_3 = {
+  count: 1,
+  criteriaSets: [
+    {
+      criteriaId: '292',
+      name: 'Complex Criteria Unit Test #3',
+      createdAt: 1722533789589,
+      updatedAt: 1722533838989,
+      searchQuery: {
+        combinator: 'Not',
+        searchQueries: [
+          {
+            combinator: 'And',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'firstName',
+                      comparatorType: 'StartsWith',
+                      value: 'A',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'lastName',
+                      comparatorType: 'StartsWith',
+                      value: 'A',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              }
+            ]
+          },
+          {
+            combinator: 'Or',
+            searchQueries: [
+              {
+                dataType: 'user',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      field: 'firstName',
+                      comparatorType: 'StartsWith',
+                      value: 'C',
+                      fieldType: 'string'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'animal-found.vaccinated',
+                      comparatorType: 'Equals',
+                      value: 'false',
+                      fieldType: 'boolean'
+                    }
+                  ]
+                }
+              },
+              {
+                dataType: 'customEvent',
+                searchCombo: {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      field: 'animal-found.count',
+                      comparatorType: 'LessThan',
+                      value: '5',
+                      fieldType: 'long'
+                    }
+                  ]
+                }
+              }
+            ]
+          }
+        ]
+      }
+    }
+  ]
+};
diff --git a/src/anonymousUserTracking/tests/criteriaCompletionChecker.test.ts b/src/anonymousUserTracking/tests/criteriaCompletionChecker.test.ts
new file mode 100644
index 00000000..931a188c
--- /dev/null
+++ b/src/anonymousUserTracking/tests/criteriaCompletionChecker.test.ts
@@ -0,0 +1,1792 @@
+import { SHARED_PREFS_EVENT_LIST_KEY } from '../../constants';
+import CriteriaCompletionChecker from '../criteriaCompletionChecker';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+describe('CriteriaCompletionChecker', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+  });
+
+  it('should return null if criteriaData is empty', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return '[]';
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria('{}');
+    expect(result).toBeNull();
+  });
+
+  it('should return criteriaId if customEvent is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'testEvent',
+            createdAt: 1708494757530,
+            dataFields: {
+              browserVisit: {
+                website: {
+                  domain: 'google.com'
+                }
+              }
+            },
+            createNewFields: true,
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'testEvent',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'browserVisit.website.domain',
+                            comparatorType: 'Equals',
+                            value: 'google.com',
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+  });
+
+  it('should return criteriaId if customEvent is matched when minMatch present', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'testEvent',
+            createdAt: 1708494757530,
+            dataFields: { browserVisit: { website: { domain: 'google.com' } } },
+            createNewFields: true,
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      minMatch: 1,
+                      maxMatch: 2,
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'testEvent',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'browserVisit.website.domain',
+                            comparatorType: 'Equals',
+                            value: 'google.com',
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+  });
+
+  it('should return criteriaId if purchase event is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            createdAt: 1708494757530,
+            items: [
+              { name: 'keyboard', id: 'fdsafds', price: 10, quantity: 2 }
+            ],
+            total: 10,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'keyboard',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.price',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '10',
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+  });
+
+  it('should return null if updateCart event with all props in item is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            createdAt: 1708494757530,
+            items: [
+              { name: 'keyboard', id: 'fdsafds', price: 10, quantity: 2 },
+              { name: 'Cofee', id: 'fdsafds', price: 10, quantity: 2 }
+            ],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'updateCart',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'keyboard',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '10',
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+  });
+
+  it('should return null if updateCart event with items is NOT matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            createdAt: 1708494757530,
+            items: [
+              { name: 'keyboard', id: 'fdsafds', price: 9, quantity: 2 },
+              { name: 'Cofee', id: 'fdsafds', price: 10, quantity: 2 }
+            ],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'updateCart',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'keyboard',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '10',
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toBeNull();
+  });
+
+  it('should return criteriaId if updateCart event is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            createdAt: 1708494757530,
+            items: [
+              { name: 'keyboard', id: 'fdsafds', price: 10, quantity: 2 }
+            ],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Equals',
+                            value: 'updateCart',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '10',
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+  });
+
+  it('should return criteriaId if criteriaData condition with numeric is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '123',
+                name: 'Black Coffee',
+                quantity: 1,
+                price: 4
+              }
+            ],
+            user: {
+              userId: 'user'
+            },
+            total: 0,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'shoppingCartItemsCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.name',
+                            comparatorType: 'Equals',
+                            value: 'Black Coffee',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.price',
+                            comparatorType: 'GreaterThanOrEqualTo',
+                            value: '4.00',
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+  });
+
+  it('should return criteriaId if criteriaData condition with StartsWith is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'testEvent',
+            createdAt: 1708494757530,
+            dataFields: undefined,
+            createNewFields: true,
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'StartsWith',
+                            value: 'test',
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+
+    const result1 = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'eventName',
+                            comparatorType: 'Contains',
+                            value: 'test',
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result1).toEqual('6');
+  });
+
+  it('should return criteriaId if criteria regex match with value is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            email: 'testEvent@example.com',
+            createdAt: 1708494757530,
+            dataFields: undefined,
+            createNewFields: true,
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '6',
+            name: 'EventCriteria',
+            createdAt: 1704754280210,
+            updatedAt: 1704754280210,
+            searchQuery: {
+              combinator: 'Or',
+              searchQueries: [
+                {
+                  combinator: 'Or',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'email',
+                            comparatorType: 'MatchesRegex',
+                            value: /^[a-zA-Z0-9]+@(?:[a-zA-Z0-9]+.)+[A-Za-z]+$/,
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('6');
+  });
+
+  // isSet criteria
+  it('should return criteriaId 97 if isset user criteria is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              country: 'UK',
+              eventTimeStamp: 10,
+              phoneNumberDetails: '99999999',
+              'shoppingCartItems.price': 50.5
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '97',
+            name: 'User',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 25,
+                            value: ''
+                          },
+                          {
+                            field: 'eventTimeStamp',
+                            fieldType: 'long',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 26,
+                            valueLong: null,
+                            value: ''
+                          },
+                          {
+                            field: 'phoneNumberDetails',
+                            fieldType: 'object',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 28,
+                            value: ''
+                          },
+                          {
+                            field: 'shoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 30,
+                            value: ''
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('97');
+  });
+
+  it('should return null (isset user criteria fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              eventTimeStamp: 10,
+              phoneNumberDetails: '99999999',
+              'shoppingCartItems.price': 50.5
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '97',
+            name: 'User',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'country',
+                            fieldType: 'string',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 25,
+                            value: ''
+                          },
+                          {
+                            field: 'eventTimeStamp',
+                            fieldType: 'long',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 26,
+                            valueLong: null,
+                            value: ''
+                          },
+                          {
+                            field: 'phoneNumberDetails',
+                            fieldType: 'object',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 28,
+                            value: ''
+                          },
+                          {
+                            field: 'shoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 30,
+                            value: ''
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 94 if isset customEvent criteria is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              animal: 'test page',
+              clickCount: '2',
+              total: 3
+            },
+            createdAt: 1700071052507,
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '94',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'button-clicked',
+                            fieldType: 'object',
+                            comparatorType: 'IsSet',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: ''
+                          },
+                          {
+                            field: 'button-clicked.animal',
+                            fieldType: 'string',
+                            comparatorType: 'IsSet',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: ''
+                          },
+                          {
+                            field: 'button-clicked.clickCount',
+                            fieldType: 'long',
+                            comparatorType: 'IsSet',
+                            dataType: 'customEvent',
+                            id: 5,
+                            valueLong: null,
+                            value: ''
+                          },
+                          {
+                            field: 'total',
+                            fieldType: 'double',
+                            comparatorType: 'IsSet',
+                            dataType: 'customEvent',
+                            id: 9,
+                            value: ''
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('94');
+  });
+
+  it('should return null (isset customEvent criteria fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              'button-clicked': { animal: 'test page' },
+              total: 3
+            },
+            createdAt: 1700071052507,
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '94',
+            name: 'Custom Event',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'button-clicked',
+                            fieldType: 'object',
+                            comparatorType: 'IsSet',
+                            dataType: 'customEvent',
+                            id: 2,
+                            value: ''
+                          },
+                          {
+                            field: 'button-clicked.animal',
+                            fieldType: 'string',
+                            comparatorType: 'IsSet',
+                            dataType: 'customEvent',
+                            id: 4,
+                            value: ''
+                          },
+                          {
+                            field: 'button-clicked.clickCount',
+                            fieldType: 'long',
+                            comparatorType: 'IsSet',
+                            dataType: 'customEvent',
+                            id: 5,
+                            valueLong: null,
+                            value: ''
+                          },
+                          {
+                            field: 'total',
+                            fieldType: 'double',
+                            comparatorType: 'IsSet',
+                            dataType: 'customEvent',
+                            id: 9,
+                            value: ''
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 96 if isset purchase criteria is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '12',
+                name: 'monitor',
+                price: 10,
+                quantity: 10
+              }
+            ],
+            total: 50,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '96',
+            name: 'Purchase',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems',
+                            fieldType: 'object',
+                            comparatorType: 'IsSet',
+                            dataType: 'purchase',
+                            id: 1,
+                            value: ''
+                          },
+                          {
+                            field: 'shoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'IsSet',
+                            dataType: 'purchase',
+                            id: 3,
+                            value: ''
+                          },
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'IsSet',
+                            dataType: 'purchase',
+                            id: 5,
+                            value: ''
+                          },
+                          {
+                            field: 'total',
+                            fieldType: 'double',
+                            comparatorType: 'IsSet',
+                            dataType: 'purchase',
+                            id: 7,
+                            value: ''
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('96');
+  });
+
+  it('should return null (isset purchase criteria fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '12',
+                name: 'monitor',
+                quantity: 10
+              }
+            ],
+            total: 50,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '96',
+            name: 'Purchase',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'shoppingCartItems',
+                            fieldType: 'object',
+                            comparatorType: 'IsSet',
+                            dataType: 'purchase',
+                            id: 1,
+                            value: ''
+                          },
+                          {
+                            field: 'shoppingCartItems.price',
+                            fieldType: 'double',
+                            comparatorType: 'IsSet',
+                            dataType: 'purchase',
+                            id: 3,
+                            value: ''
+                          },
+                          {
+                            field: 'shoppingCartItems.name',
+                            fieldType: 'string',
+                            comparatorType: 'IsSet',
+                            dataType: 'purchase',
+                            id: 5,
+                            value: ''
+                          },
+                          {
+                            field: 'total',
+                            fieldType: 'double',
+                            comparatorType: 'IsSet',
+                            dataType: 'purchase',
+                            id: 7,
+                            value: ''
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 95 if isset updateCart criteria is matched', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', price: 50, quantity: 50 }],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '95',
+            name: 'UpdateCart: isSet Comparator',
+            createdAt: 1719328291857,
+            updatedAt: 1719328291857,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart',
+                            comparatorType: 'IsSet',
+                            value: '',
+                            fieldType: 'object'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'IsSet',
+                            value: '',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'IsSet',
+                            value: '',
+                            fieldType: 'double'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            comparatorType: 'IsSet',
+                            value: '',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('95');
+  });
+
+  it('should return null (isset updateCart criteria fail)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'Mocha', quantity: 50 }],
+            eventType: 'cartUpdate'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '95',
+            name: 'UpdateCart: isSet Comparator',
+            createdAt: 1719328291857,
+            updatedAt: 1719328291857,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'customEvent',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart',
+                            comparatorType: 'IsSet',
+                            value: '',
+                            fieldType: 'object'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.name',
+                            comparatorType: 'IsSet',
+                            value: '',
+                            fieldType: 'string'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field: 'updateCart.updatedShoppingCartItems.price',
+                            comparatorType: 'IsSet',
+                            value: '',
+                            fieldType: 'double'
+                          },
+                          {
+                            dataType: 'customEvent',
+                            field:
+                              'updateCart.updatedShoppingCartItems.quantity',
+                            comparatorType: 'IsSet',
+                            value: '',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 100 (boolean test)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              subscribed: true,
+              phoneNumber: '99999999'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '100',
+            name: 'User',
+            createdAt: 1716560453973,
+            updatedAt: 1716560453973,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            field: 'subscribed',
+                            fieldType: 'boolean',
+                            comparatorType: 'Equals',
+                            dataType: 'user',
+                            id: 25,
+                            value: 'true'
+                          },
+                          {
+                            field: 'phoneNumber',
+                            fieldType: 'String',
+                            comparatorType: 'IsSet',
+                            dataType: 'user',
+                            id: 28,
+                            value: ''
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('100');
+  });
+
+  it('should return criteriaId 194 if Contact: Phone Number != 57688559', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              subscribed: true,
+              phoneNumber: '123685748641'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '194',
+            name: 'Contact: Phone Number != 57688559',
+            createdAt: 1721337331194,
+            updatedAt: 1722338525737,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'phoneNumber',
+                            comparatorType: 'DoesNotEqual',
+                            value: '57688559',
+                            fieldType: 'string'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('194');
+  });
+
+  it('should return criteriaId 293 if Contact: subscribed != false', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              subscribed: true,
+              phoneNumber: '123685748641'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '293',
+            name: 'Contact: subscribed != false',
+            createdAt: 1722605666776,
+            updatedAt: 1722606283109,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'user',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'user',
+                            field: 'subscribed',
+                            comparatorType: 'DoesNotEqual',
+                            value: 'false',
+                            fieldType: 'boolean'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('293');
+  });
+
+  it('should return criteriaId 297 if Purchase: shoppingCartItems.quantity != 12345678', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '12',
+                name: 'monitor',
+                price: 50,
+                quantity: 10
+              }
+            ],
+            total: 50,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '297',
+            name: 'Purchase: shoppingCartItems.quantity != 12345678',
+            createdAt: 1722667099444,
+            updatedAt: 1722667361286,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.quantity',
+                            comparatorType: 'DoesNotEqual',
+                            value: '12345678',
+                            fieldType: 'long'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('297');
+  });
+
+  it('should return criteriaId 298 if Purchase: shoppingCartItems.price != 105', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [
+              {
+                id: '12',
+                name: 'monitor',
+                price: 50.5,
+                quantity: 10
+              }
+            ],
+            total: 50,
+            eventType: 'purchase'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify({
+        count: 1,
+        criteriaSets: [
+          {
+            criteriaId: '298',
+            name: 'Purchase: shoppingCartItems.price != 105',
+            createdAt: 1722606251607,
+            updatedAt: 1722606295791,
+            searchQuery: {
+              combinator: 'And',
+              searchQueries: [
+                {
+                  combinator: 'And',
+                  searchQueries: [
+                    {
+                      dataType: 'purchase',
+                      searchCombo: {
+                        combinator: 'And',
+                        searchQueries: [
+                          {
+                            dataType: 'purchase',
+                            field: 'shoppingCartItems.price',
+                            comparatorType: 'DoesNotEqual',
+                            value: '105',
+                            fieldType: 'double'
+                          }
+                        ]
+                      }
+                    }
+                  ]
+                }
+              ]
+            }
+          }
+        ]
+      })
+    );
+    expect(result).toEqual('298');
+  });
+});
diff --git a/src/anonymousUserTracking/tests/dataTypeComparatorSearchQueryCriteria.test.ts b/src/anonymousUserTracking/tests/dataTypeComparatorSearchQueryCriteria.test.ts
new file mode 100644
index 00000000..e75cf9f4
--- /dev/null
+++ b/src/anonymousUserTracking/tests/dataTypeComparatorSearchQueryCriteria.test.ts
@@ -0,0 +1,439 @@
+import { SHARED_PREFS_EVENT_LIST_KEY } from '../../constants';
+import CriteriaCompletionChecker from '../criteriaCompletionChecker';
+import {
+  DATA_TYPE_COMPARATOR_DOES_NOT_EQUAL,
+  DATA_TYPE_COMPARATOR_EQUALS,
+  DATA_TYPE_COMPARATOR_GREATER_THAN,
+  DATA_TYPE_COMPARATOR_GREATER_THAN_OR_EQUAL_TO,
+  DATA_TYPE_COMPARATOR_IS_SET,
+  DATA_TYPE_COMPARATOR_LESS_THAN,
+  DATA_TYPE_COMPARATOR_LESS_THAN_OR_EQUAL_TO
+} from './constants';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+describe('dataTypeComparatorSearchQueryCriteria', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+  });
+
+  it('should return criteriaId 285 (Comparator test For Equal)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 19.99,
+              likes_boba: true,
+              country: 'Chaina',
+              eventTimeStamp: 3
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_EQUALS)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return null (Comparator test For Equal - No Match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 10.99,
+              eventTimeStamp: 30,
+              likes_boba: false,
+              country: 'Taiwan'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_EQUALS)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 285 (Comparator test For DoesNotEqual)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 11.2,
+              eventTimeStamp: 30,
+              likes_boba: false
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_DOES_NOT_EQUAL)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return null (Comparator test For DoesNotEqual - No Match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 10.99,
+              eventTimeStamp: 30,
+              likes_boba: true
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_DOES_NOT_EQUAL)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 289 (Comparator test For LessThan)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 10,
+              eventTimeStamp: 14
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_LESS_THAN)
+    );
+    expect(result).toEqual('289');
+  });
+
+  it('should return null (Comparator test For LessThan - No Match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 10,
+              eventTimeStamp: 18
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_LESS_THAN)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 290 (Comparator test For LessThanOrEqualTo)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 17,
+              eventTimeStamp: 14
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_LESS_THAN_OR_EQUAL_TO)
+    );
+    expect(result).toEqual('290');
+  });
+
+  it('should return null (Comparator test For LessThanOrEqualTo - No Match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 18,
+              eventTimeStamp: 12
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_LESS_THAN_OR_EQUAL_TO)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 290 (Comparator test For GreaterThan)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 56,
+              eventTimeStamp: 51
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_GREATER_THAN)
+    );
+    expect(result).toEqual('290');
+  });
+
+  it('should return null (Comparator test For GreaterThan - No Match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 5,
+              eventTimeStamp: 3
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_GREATER_THAN)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 291 (Comparator test For GreaterThanOrEqualTo)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 20,
+              eventTimeStamp: 30
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_GREATER_THAN_OR_EQUAL_TO)
+    );
+    expect(result).toEqual('291');
+  });
+
+  it('should return null (Comparator test For GreaterThanOrEqualTo - No Match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 18,
+              eventTimeStamp: 16
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_GREATER_THAN_OR_EQUAL_TO)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 285 (Comparator test For IsSet)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: 10,
+              eventTimeStamp: 20,
+              saved_cars: '10',
+              country: 'Taiwan'
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_IS_SET)
+    );
+    expect(result).toEqual('285');
+  });
+
+  it('should return criteriaId 285 (Comparator test For IsSet - No Match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              savings: '',
+              eventTimeStamp: '',
+              saved_cars: 'd',
+              country: ''
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(DATA_TYPE_COMPARATOR_IS_SET)
+    );
+    expect(result).toEqual(null);
+  });
+});
diff --git a/src/anonymousUserTracking/tests/nestedTesting.test.ts b/src/anonymousUserTracking/tests/nestedTesting.test.ts
new file mode 100644
index 00000000..207c9328
--- /dev/null
+++ b/src/anonymousUserTracking/tests/nestedTesting.test.ts
@@ -0,0 +1,469 @@
+import { SHARED_PREFS_EVENT_LIST_KEY } from '../../constants';
+import CriteriaCompletionChecker from '../criteriaCompletionChecker';
+import {
+  NESTED_CRITERIA,
+  NESTED_CRITERIA_MULTI_LEVEL,
+  NESTED_CRITERIA_MULTI_LEVEL_ARRAY,
+  NESTED_CRITERIA_MULTI_LEVEL_ARRAY_TRACK_EVENT,
+  NESTED_CRITERIA_MULTI_LEVEL_MORE_THAN_4_EVENTS
+} from './constants';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+describe('nestedTesting', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+  });
+
+  it('should return criteriaId 168 (nested field)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              email: 'user@example.com',
+              furniture: [
+                {
+                  furnitureType: 'Sofa',
+                  furnitureColor: 'White',
+                  lengthInches: 40,
+                  widthInches: 60
+                },
+                {
+                  furnitureType: 'table',
+                  furnitureColor: 'Gray',
+                  lengthInches: 20,
+                  widthInches: 30
+                }
+              ]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(JSON.stringify(NESTED_CRITERIA));
+    expect(result).toEqual('168');
+  });
+
+  it('should return criteriaId null (nested field - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              email: 'user@example.com',
+              furniture: [
+                {
+                  furnitureType: 'Sofa',
+                  furnitureColor: 'Gray',
+                  lengthInches: 40,
+                  widthInches: 60
+                },
+                {
+                  furnitureType: 'table',
+                  furnitureColor: 'White',
+                  lengthInches: 20,
+                  widthInches: 30
+                }
+              ]
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(JSON.stringify(NESTED_CRITERIA));
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 425 (Multi level Nested field criteria)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              browserVisit: { website: { domain: 'https://mybrand.com/socks' } }
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL)
+    );
+    expect(result).toEqual('425');
+  });
+
+  it('should return criteriaId 425 (Multi level Nested field criteria - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              'button-clicked': {
+                browserVisit: {
+                  website: { domain: 'https://mybrand.com/socks' }
+                }
+              }
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId null (Multi level Nested field criteria - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              'browserVisit.website.domain': 'https://mybrand.com/socks'
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId null (Multi level Nested field criteria - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              browserVisit: { website: { domain: 'https://mybrand.com' } }
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId null (Multi level Nested field criteria - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'button-clicked',
+            dataFields: {
+              quantity: 11,
+              domain: 'https://mybrand.com/socks'
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 436 (Multi level Nested field criteria)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              furniture: {
+                material: [
+                  {
+                    type: 'table',
+                    color: 'black',
+                    lengthInches: 40,
+                    widthInches: 60
+                  },
+                  {
+                    type: 'Sofa',
+                    color: 'Gray',
+                    lengthInches: 20,
+                    widthInches: 30
+                  }
+                ]
+              }
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL_ARRAY)
+    );
+    expect(result).toEqual('436');
+  });
+
+  it('should return criteriaId null (Multi level Nested field criteria - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            dataFields: {
+              furniture: {
+                material: [
+                  {
+                    type: 'table',
+                    color: 'Gray',
+                    lengthInches: 40,
+                    widthInches: 60
+                  },
+                  {
+                    type: 'Sofa',
+                    color: 'black',
+                    lengthInches: 20,
+                    widthInches: 30
+                  }
+                ]
+              }
+            },
+            eventType: 'user'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL_ARRAY)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 459 (Multi level Nested field criteria)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'TopLevelArrayObject',
+            dataFields: {
+              a: {
+                h: [
+                  {
+                    b: 'e',
+                    c: 'h'
+                  },
+                  {
+                    b: 'd',
+                    c: 'g'
+                  }
+                ]
+              }
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL_ARRAY_TRACK_EVENT)
+    );
+    expect(result).toEqual('459');
+  });
+
+  it('should return criteriaId null (Multi level Nested field criteria - No match)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            eventName: 'TopLevelArrayObject',
+            dataFields: {
+              a: {
+                h: [
+                  {
+                    b: 'd',
+                    c: 'h'
+                  },
+                  {
+                    b: 'e',
+                    c: 'g'
+                  }
+                ]
+              }
+            },
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL_ARRAY_TRACK_EVENT)
+    );
+    expect(result).toEqual(null);
+  });
+
+  it('should return criteriaId 484 (Multi level Nested field criteria for more than 3 events)', () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            items: [{ id: '12', name: 'monitor', price: 50, quantity: 10 }],
+            total: 50,
+            eventType: 'purchase'
+          },
+          {
+            items: [
+              { name: 'piano', id: 'fdsafds', price: 100, quantity: 2 },
+              { name: 'piano2', id: 'fdsafds2', price: 100, quantity: 5 }
+            ],
+            eventType: 'cartUpdate',
+            preferUserId: true,
+            createdAt: 1729585174
+          },
+          { likes_boba: 'true', eventType: 'user' },
+          {
+            eventName: 'cancelled_booking',
+            createdAt: 1729585183,
+            dataFields: { details: { event: { name: 'dummy' } } },
+            createNewFields: true,
+            eventType: 'customEvent'
+          },
+          {
+            eventName: 'cancelled_booking',
+            createdAt: 1729585192,
+            dataFields: { details: { event: { name: 'haircut' } } },
+            createNewFields: true,
+            eventType: 'customEvent'
+          }
+        ]);
+      }
+
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(NESTED_CRITERIA_MULTI_LEVEL_MORE_THAN_4_EVENTS)
+    );
+    expect(result).toEqual('484');
+  });
+});
diff --git a/src/anonymousUserTracking/tests/userMergeScenarios.test.ts b/src/anonymousUserTracking/tests/userMergeScenarios.test.ts
new file mode 100644
index 00000000..88dcce04
--- /dev/null
+++ b/src/anonymousUserTracking/tests/userMergeScenarios.test.ts
@@ -0,0 +1,953 @@
+import MockAdapter from 'axios-mock-adapter';
+import { GenerateJWTPayload, initializeWithConfig } from '../../authorization';
+import {
+  SHARED_PREFS_EVENT_LIST_KEY,
+  SHARED_PREFS_CRITERIA,
+  GETMESSAGES_PATH,
+  ENDPOINT_TRACK_ANON_SESSION,
+  GET_CRITERIA_PATH,
+  SHARED_PREFS_ANON_SESSIONS,
+  ENDPOINT_MERGE_USER,
+  SHARED_PREF_ANON_USER_ID,
+  SHARED_PREF_ANON_USAGE_TRACKED,
+  SHARED_PREF_USER_TOKEN
+} from '../../constants';
+import { track } from '../../events';
+import { getInAppMessages } from '../../inapp';
+import { baseAxiosRequest } from '../../request';
+import { USER_MERGE_SCENARIO_CRITERIA } from './constants';
+import { setTypeOfAuth } from '../../utils/typeOfAuth';
+
+jest.setTimeout(20000); // Set the timeout to 10 seconds
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+const eventData = {
+  eventName: 'testEvent123',
+  dataFields: undefined,
+  createNewFields: true,
+  eventType: 'customEvent'
+};
+
+const eventDataMatched = {
+  eventName: 'testEvent',
+  dataFields: undefined,
+  createNewFields: true,
+  eventType: 'customEvent'
+};
+
+const initialAnonSessionInfo = {
+  itbl_anon_sessions: {
+    number_of_sessions: 1,
+    first_session: 123456789,
+    last_session: expect.any(Number)
+  }
+};
+
+declare global {
+  function uuidv4(): string;
+  function getEmail(): string;
+  function getUserID(): string;
+  function setUserID(): string;
+}
+const mockRequest = new MockAdapter(baseAxiosRequest);
+// const mockOnPostSpy = jest.spyOn(mockRequest, 'onPost');
+
+const MOCK_JWT_KEY =
+  'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzA2MTc3MzQsImlhdCI6MTYzMDYxNzQzNCwiZW1haWwiOiJ3aWR0aC50ZXN0ZXJAZ21haWwuY29tIn0.knLmbgO8kKM9CHP2TH2v85OSC2Jorh2JjRm76FFsPQc';
+const MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY =
+  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3RAdGVzdC5jb20iLCJleHAiOjE2Nzk0ODMyOTEsImlhdCI6MTY3OTQ4MzIzMX0.APaQAYy-lTE0o8rbR6b6-28eCICq36SQMBXmeZAvk1k';
+
+describe('UserMergeScenariosTests', () => {
+  beforeAll(() => {
+    (global as any).localStorage = localStorageMock;
+    global.window = Object.create({ location: { hostname: 'google.com' } });
+    mockRequest.onGet(GETMESSAGES_PATH).reply(200, {
+      data: 'something'
+    });
+    mockRequest.onPost('/events/track').reply(200, {});
+    mockRequest.onPost(ENDPOINT_MERGE_USER).reply(200, {});
+    mockRequest.onGet(GET_CRITERIA_PATH).reply(200, {});
+    mockRequest.onPost(ENDPOINT_TRACK_ANON_SESSION).reply(200, {});
+  });
+
+  beforeEach(() => {
+    mockRequest.reset();
+    mockRequest.resetHistory();
+    mockRequest.onGet(GETMESSAGES_PATH).reply(200, {
+      data: 'something'
+    });
+    mockRequest.onPost('/events/track').reply(200, {});
+    mockRequest.onPost(ENDPOINT_MERGE_USER).reply(200, {});
+    mockRequest.onGet(GET_CRITERIA_PATH).reply(200, {});
+    mockRequest.onPost(ENDPOINT_TRACK_ANON_SESSION).reply(200, {});
+    jest.resetAllMocks();
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([eventData]);
+      }
+      if (key === SHARED_PREFS_CRITERIA) {
+        return JSON.stringify(USER_MERGE_SCENARIO_CRITERIA);
+      }
+      if (key === SHARED_PREFS_ANON_SESSIONS) {
+        return JSON.stringify(initialAnonSessionInfo);
+      }
+      if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+        return 'true';
+      }
+      return null;
+    });
+    jest.useFakeTimers();
+  });
+
+  describe('UserMergeScenariosTests with setUserID', () => {
+    it('criteria not met with merge false with setUserId', async () => {
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: false,
+            mergeOnAnonymousToKnown: false
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ eventName: 'testEvent123' });
+      } catch (e) {
+        console.log('');
+      }
+      expect(localStorage.setItem).toHaveBeenCalledWith(
+        SHARED_PREFS_EVENT_LIST_KEY,
+        expect.any(String)
+      );
+      await setUserID('testuser123');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.userId).toBe('testuser123');
+      const removeItemCalls = localStorageMock.removeItem.mock.calls.filter(
+        (call) => call[0] === SHARED_PREFS_EVENT_LIST_KEY
+      );
+      // count 2 is because we want to remove the anon user and remove anon details
+      expect(removeItemCalls.length).toBe(2);
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('criteria not met with merge true with setUserId', async () => {
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: true
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ ...eventData });
+      } catch (e) {
+        console.log('');
+      }
+      expect(localStorage.setItem).toHaveBeenCalledWith(
+        SHARED_PREFS_EVENT_LIST_KEY,
+        expect.any(String)
+      );
+      await setUserID('testuser123');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.userId).toBe('testuser123');
+      const removeItemCalls = localStorageMock.removeItem.mock.calls.filter(
+        (call) => call[0] === SHARED_PREFS_EVENT_LIST_KEY
+      );
+      // count 2 means it removed items and so syncEvents was called
+      // because removeItem gets called one time for
+      // the key in case of logout and 2nd time on syncevents
+      expect(removeItemCalls.length).toBe(2);
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('criteria not met with merge default value with setUserId', async () => {
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: false
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ eventName: 'testEvent123' });
+      } catch (e) {
+        console.log('');
+      }
+      expect(localStorage.setItem).toHaveBeenCalledWith(
+        SHARED_PREFS_EVENT_LIST_KEY,
+        expect.any(String)
+      );
+      await setUserID('testuser123');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.userId).toBe('testuser123');
+      const removeItemCalls = localStorageMock.removeItem.mock.calls.filter(
+        (call) => call[0] === SHARED_PREFS_EVENT_LIST_KEY
+      );
+      // count 2 means it removed items and so syncEvents was called
+
+      // because removeItem gets called one time for
+      // the key in case of logout and 2nd time on syncevents
+      expect(removeItemCalls.length).toBe(2);
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('criteria is met with merge false with setUserId', async () => {
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+          return JSON.stringify([eventDataMatched]);
+        }
+        if (key === SHARED_PREFS_CRITERIA) {
+          return JSON.stringify(USER_MERGE_SCENARIO_CRITERIA);
+        }
+        if (key === SHARED_PREFS_ANON_SESSIONS) {
+          return JSON.stringify(initialAnonSessionInfo);
+        }
+        return null;
+      });
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: false
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('');
+      }
+      await setUserID('testuser123');
+      expect(localStorageMock.removeItem).toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.userId).toBe('testuser123');
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('criteria is met with merge true with setUserId', async () => {
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+          return JSON.stringify([eventDataMatched]);
+        }
+        if (key === SHARED_PREFS_CRITERIA) {
+          return JSON.stringify(USER_MERGE_SCENARIO_CRITERIA);
+        }
+        if (key === SHARED_PREFS_ANON_SESSIONS) {
+          return JSON.stringify(initialAnonSessionInfo);
+        }
+        if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+          return 'true';
+        }
+        return null;
+      });
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: true
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      // this function call is needed for putting some delay before executing setUserId
+      try {
+        await getInAppMessages({
+          count: 10,
+          packageName: 'my-lil-website'
+        });
+      } catch (e) {
+        console.log(e);
+      }
+      await setUserID('testuser123');
+      expect(localStorageMock.removeItem).toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      jest.useFakeTimers();
+      setTimeout(() => {
+        const mergePostRequestData = mockRequest.history.post.find(
+          (req) => req.url === ENDPOINT_MERGE_USER
+        );
+        expect(mergePostRequestData).toBeDefined(); // ensure that merge API gets called
+      }, 1000);
+      jest.runAllTimers();
+    });
+
+    it('criteria is met with merge default with setUserId', async () => {
+      const anonId = '123e4567-e89b-12d3-a456-426614174000';
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+          return JSON.stringify([eventDataMatched]);
+        }
+        if (key === SHARED_PREFS_CRITERIA) {
+          return JSON.stringify(USER_MERGE_SCENARIO_CRITERIA);
+        }
+        if (key === SHARED_PREFS_ANON_SESSIONS) {
+          return JSON.stringify(initialAnonSessionInfo);
+        }
+        if (key === SHARED_PREF_ANON_USER_ID) {
+          return anonId;
+        }
+        return null;
+      });
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      try {
+        await getInAppMessages({
+          count: 10,
+          packageName: 'my-lil-website'
+        });
+      } catch (e) {
+        console.log(e);
+      }
+      setTypeOfAuth('userID');
+      await setUserID('testuser123');
+      expect(localStorageMock.removeItem).toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      jest.useFakeTimers();
+      setTimeout(() => {
+        const mergePostRequestData = mockRequest.history.post.find(
+          (req) => req.url === ENDPOINT_MERGE_USER
+        );
+        expect(mergePostRequestData).toBeDefined(); // ensure that merge API gets called
+      }, 1000);
+      jest.runAllTimers();
+    });
+
+    it('current user identified with setUserId merge false', async () => {
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: false
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      await setUserID('testuser123');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.userId).toBe('testuser123');
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      expect(localStorageMock.setItem).not.toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      await setUserID('testuseranotheruser');
+      const secondResponse = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(secondResponse.config.params.userId).toBe('testuseranotheruser');
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('current user identified with setUserId merge true', async () => {
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: true
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      await setUserID('testuser123');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.userId).toBe('testuser123');
+      expect(localStorageMock.setItem).not.toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      await setUserID('testuseranotheruser');
+      const secondResponse = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(secondResponse.config.params.userId).toBe('testuseranotheruser');
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeDefined(); // ensure that merge API gets called
+    });
+
+    it('merge api called with destination userID JWT Authorization', async () => {
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: true
+          }
+        },
+        generateJWT: (payload: GenerateJWTPayload) => {
+          if (payload.userID === 'testuseranotheruser') {
+            return Promise.resolve(MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY);
+          }
+          return Promise.resolve(MOCK_JWT_KEY);
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREF_USER_TOKEN) {
+          return MOCK_JWT_KEY;
+        }
+        return null;
+      });
+      await setUserID('testuser123');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.headers.Authorization).toBe(
+        `Bearer ${MOCK_JWT_KEY}`
+      );
+      expect(response.config.params.userId).toBe('testuser123');
+      expect(localStorageMock.setItem).not.toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREF_USER_TOKEN) {
+          return MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY;
+        }
+        return null;
+      });
+      await setUserID('testuseranotheruser');
+      const secondResponse = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(secondResponse.config.headers.Authorization).toBe(
+        `Bearer ${MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY}`
+      );
+      expect(secondResponse.config.params.userId).toBe('testuseranotheruser');
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData?.headers?.Authorization).toBe(
+        `Bearer ${MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY}`
+      );
+      expect(mergePostRequestData).toBeDefined(); // ensure that merge API gets called
+      logout(); // logout to remove logged in users after this test
+    });
+
+    it('current user identified with setUserId merge default', async () => {
+      const { setUserID, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: false
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      await setUserID('testuser123');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.userId).toBe('testuser123');
+      expect(localStorageMock.setItem).not.toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      await setUserID('testuseranotheruser');
+      const secondResponse = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(secondResponse.config.params.userId).toBe('testuseranotheruser');
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+  });
+
+  describe('UserMergeScenariosTests with setEmail', () => {
+    it('criteria not met with merge false with setEmail', async () => {
+      const { setEmail, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: false,
+            mergeOnAnonymousToKnown: false
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ eventName: 'testEvent123' });
+      } catch (e) {
+        console.log('');
+      }
+      expect(localStorage.setItem).toHaveBeenCalledWith(
+        SHARED_PREFS_EVENT_LIST_KEY,
+        expect.any(String)
+      );
+      await setEmail('testuser123@test.com');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.email).toBe('testuser123@test.com');
+      const removeItemCalls = localStorageMock.removeItem.mock.calls.filter(
+        (call) => call[0] === SHARED_PREFS_EVENT_LIST_KEY
+      );
+      // count 2 is because we want to remove the anon user and remove anon details
+      expect(removeItemCalls.length).toBe(2);
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('criteria not met with merge true with setEmail', async () => {
+      const { setEmail, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: true
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ ...eventData });
+      } catch (e) {
+        console.log('');
+      }
+      expect(localStorage.setItem).toHaveBeenCalledWith(
+        SHARED_PREFS_EVENT_LIST_KEY,
+        expect.any(String)
+      );
+      await setEmail('testuser123@test.com');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.email).toBe('testuser123@test.com');
+      const removeItemCalls = localStorageMock.removeItem.mock.calls.filter(
+        (call) => call[0] === SHARED_PREFS_EVENT_LIST_KEY
+      );
+      // count 2 means it removed items and so syncEvents was called
+
+      // because removeItem gets called one time for
+      // the key in case of logout and 2nd time on syncevents
+      expect(removeItemCalls.length).toBe(2);
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('criteria not met with merge default value with setEmail', async () => {
+      const { setEmail, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ eventName: 'testEvent123' });
+      } catch (e) {
+        console.log('');
+      }
+      expect(localStorage.setItem).toHaveBeenCalledWith(
+        SHARED_PREFS_EVENT_LIST_KEY,
+        expect.any(String)
+      );
+      await setEmail('testuser123@test.com');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.email).toBe('testuser123@test.com');
+      const removeItemCalls = localStorageMock.removeItem.mock.calls.filter(
+        (call) => call[0] === SHARED_PREFS_EVENT_LIST_KEY
+      );
+      // count 2 means it removed items and so syncEvents was called
+
+      // because removeItem gets called one time for
+      // the key in case of logout and 2nd time on syncevents
+      expect(removeItemCalls.length).toBe(2);
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('criteria is met with merge true with setEmail', async () => {
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+          return JSON.stringify([eventDataMatched]);
+        }
+        if (key === SHARED_PREFS_CRITERIA) {
+          return JSON.stringify(USER_MERGE_SCENARIO_CRITERIA);
+        }
+        if (key === SHARED_PREFS_ANON_SESSIONS) {
+          return JSON.stringify(initialAnonSessionInfo);
+        }
+        if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+          return 'true';
+        }
+        return null;
+      });
+      const { setEmail } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: true
+          }
+        }
+      });
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      try {
+        await getInAppMessages({
+          count: 10,
+          packageName: 'my-lil-website'
+        });
+      } catch (e) {
+        console.log(e);
+      }
+      await setEmail('testuser123@test.com');
+      expect(localStorageMock.removeItem).toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      jest.useFakeTimers();
+      setTimeout(() => {
+        const mergePostRequestData = mockRequest.history.post.find(
+          (req) => req.url === ENDPOINT_MERGE_USER
+        );
+        expect(mergePostRequestData).toBeDefined(); // ensure that merge API gets called
+      }, 1500);
+      jest.runAllTimers();
+    });
+
+    it('criteria is met with merge default with setEmail', async () => {
+      const anonId = '123e4567-e89b-12d3-a456-426614174000';
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+          return JSON.stringify([eventDataMatched]);
+        }
+        if (key === SHARED_PREFS_CRITERIA) {
+          return JSON.stringify(USER_MERGE_SCENARIO_CRITERIA);
+        }
+        if (key === SHARED_PREFS_ANON_SESSIONS) {
+          return JSON.stringify(initialAnonSessionInfo);
+        }
+        if (key === SHARED_PREF_ANON_USER_ID) {
+          return anonId;
+        }
+        return null;
+      });
+      const { setEmail, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      try {
+        await getInAppMessages({
+          count: 10,
+          packageName: 'my-lil-website'
+        });
+      } catch (e) {
+        console.log(e);
+      }
+      setTypeOfAuth('userID');
+      await setEmail('testuser123@test.com');
+      expect(localStorageMock.removeItem).toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      jest.useFakeTimers();
+      setTimeout(() => {
+        const mergePostRequestData = mockRequest.history.post.find(
+          (req) => req.url === ENDPOINT_MERGE_USER
+        );
+        expect(mergePostRequestData).toBeDefined(); // ensure that merge API gets called
+      }, 1500);
+      jest.runAllTimers();
+    });
+
+    it('current user identified with setEmail with merge false', async () => {
+      const { setEmail, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: false
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      await setEmail('testuser123@test.com');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.email).toBe('testuser123@test.com');
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      expect(localStorageMock.setItem).not.toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      await setEmail('testuseranotheruser@test.com');
+      const secondResponse = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(secondResponse.config.params.email).toBe(
+        'testuseranotheruser@test.com'
+      );
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('current user identified with setEmail merge true', async () => {
+      const { setEmail, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: true
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      await setEmail('testuser123@test.com');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.email).toBe('testuser123@test.com');
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      expect(localStorageMock.setItem).not.toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      await setEmail('testuseranotheruser@test.com');
+      const secondResponse = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(secondResponse.config.params.email).toBe(
+        'testuseranotheruser@test.com'
+      );
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeDefined(); // ensure that merge API gets called
+    });
+
+    it('current user identified with setEmail merge default', async () => {
+      const { setEmail, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: false
+          }
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      await setEmail('testuser123@test.com');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.params.email).toBe('testuser123@test.com');
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      expect(localStorageMock.setItem).not.toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      await setEmail('testuseranotheruser@test.com');
+      const secondResponse = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(secondResponse.config.params.email).toBe(
+        'testuseranotheruser@test.com'
+      );
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData).toBeUndefined(); // ensure that merge API Do NOT get called
+    });
+
+    it('merge api called with destination email JWT Authorization', async () => {
+      const { setEmail, logout } = initializeWithConfig({
+        authToken: '123',
+        configOptions: {
+          enableAnonActivation: true,
+          identityResolution: {
+            replayOnVisitorToKnown: true,
+            mergeOnAnonymousToKnown: true
+          }
+        },
+        generateJWT: (payload: GenerateJWTPayload) => {
+          if (payload.email === 'testuseranotheruser@test.com') {
+            return Promise.resolve(MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY);
+          }
+          return Promise.resolve(MOCK_JWT_KEY);
+        }
+      });
+      logout(); // logout to remove logged in users before this test
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREF_USER_TOKEN) {
+          return MOCK_JWT_KEY;
+        }
+        return null;
+      });
+      await setEmail('testuser123@test.com');
+      const response = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(response.config.headers.Authorization).toBe(
+        `Bearer ${MOCK_JWT_KEY}`
+      );
+      expect(response.config.params.email).toBe('testuser123@test.com');
+      try {
+        await track({ eventName: 'testEvent' });
+      } catch (e) {
+        console.log('', e);
+      }
+      expect(localStorageMock.setItem).not.toHaveBeenCalledWith(
+        SHARED_PREF_ANON_USER_ID
+      );
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREF_USER_TOKEN) {
+          return MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY;
+        }
+        return null;
+      });
+      await setEmail('testuseranotheruser@test.com');
+      const secondResponse = await getInAppMessages({
+        count: 10,
+        packageName: 'my-lil-website'
+      });
+      expect(secondResponse.config.headers.Authorization).toBe(
+        `Bearer ${MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY}`
+      );
+      expect(secondResponse.config.params.email).toBe(
+        'testuseranotheruser@test.com'
+      );
+      const mergePostRequestData = mockRequest.history.post.find(
+        (req) => req.url === ENDPOINT_MERGE_USER
+      );
+      expect(mergePostRequestData?.headers?.Authorization).toBe(
+        `Bearer ${MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY}`
+      );
+      expect(mergePostRequestData).toBeDefined(); // ensure that merge API gets called
+    });
+  });
+});
diff --git a/src/anonymousUserTracking/tests/userUpdate.test.ts b/src/anonymousUserTracking/tests/userUpdate.test.ts
new file mode 100644
index 00000000..579cffb6
--- /dev/null
+++ b/src/anonymousUserTracking/tests/userUpdate.test.ts
@@ -0,0 +1,146 @@
+import MockAdapter from 'axios-mock-adapter';
+import { baseAxiosRequest } from '../../request';
+import {
+  SHARED_PREFS_ANON_SESSIONS,
+  SHARED_PREFS_EVENT_LIST_KEY,
+  SHARED_PREFS_CRITERIA,
+  GET_CRITERIA_PATH,
+  ENDPOINT_TRACK_ANON_SESSION,
+  ENDPOINT_MERGE_USER,
+  SHARED_PREF_ANON_USAGE_TRACKED
+} from '../../constants';
+import { updateUser } from '../../users';
+import { initializeWithConfig } from '../../authorization';
+import { CUSTOM_EVENT_API_TEST_CRITERIA } from './constants';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+declare global {
+  function uuidv4(): string;
+  function getEmail(): string;
+  function getUserID(): string;
+  function setUserID(): string;
+}
+
+const eventDataMatched = {
+  eventName: 'animal-found',
+  dataFields: {
+    type: 'cat',
+    count: 6,
+    vaccinated: true
+  },
+  createNewFields: true,
+  eventType: 'customEvent'
+};
+
+const userDataMatched = {
+  dataFields: {
+    furniture: {
+      furnitureType: 'Sofa',
+      furnitureColor: 'White'
+    }
+  },
+  eventType: 'user'
+};
+
+const initialAnonSessionInfo = {
+  itbl_anon_sessions: {
+    number_of_sessions: 1,
+    first_session: 123456789,
+    last_session: expect.any(Number)
+  }
+};
+
+const mockRequest = new MockAdapter(baseAxiosRequest);
+
+describe('UserUpdate', () => {
+  beforeAll(() => {
+    (global as any).localStorage = localStorageMock;
+    global.window = Object.create({ location: { hostname: 'google.com' } });
+    mockRequest.onPost('/events/track').reply(200, {});
+    mockRequest.onPost('/users/update').reply(200, {});
+    mockRequest.onGet(GET_CRITERIA_PATH).reply(200, {});
+    mockRequest.onPost(ENDPOINT_TRACK_ANON_SESSION).reply(200, {});
+  });
+
+  beforeEach(() => {
+    mockRequest.reset();
+    mockRequest.resetHistory();
+    mockRequest.onPost('/events/track').reply(200, {});
+    mockRequest.onPost('/users/update').reply(200, {});
+    mockRequest.onPost(ENDPOINT_MERGE_USER).reply(200, {});
+    mockRequest.onGet(GET_CRITERIA_PATH).reply(200, {});
+    mockRequest.onPost(ENDPOINT_TRACK_ANON_SESSION).reply(200, {});
+    jest.resetAllMocks();
+    jest.useFakeTimers();
+  });
+
+  it('should not have unnecessary extra nesting when locally stored user update fields are sent to server', async () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            ...userDataMatched.dataFields,
+            eventType: userDataMatched.eventType
+          },
+          eventDataMatched
+        ]);
+      }
+      if (key === SHARED_PREFS_CRITERIA) {
+        return JSON.stringify(CUSTOM_EVENT_API_TEST_CRITERIA);
+      }
+      if (key === SHARED_PREFS_ANON_SESSIONS) {
+        return JSON.stringify(initialAnonSessionInfo);
+      }
+      if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+        return 'true';
+      }
+      return null;
+    });
+
+    const { logout } = initializeWithConfig({
+      authToken: '123',
+      configOptions: { enableAnonActivation: true }
+    });
+    logout(); // logout to remove logged in users before this test
+
+    try {
+      await updateUser();
+    } catch (e) {
+      console.log('');
+    }
+    expect(localStorage.setItem).toHaveBeenCalledWith(
+      SHARED_PREFS_EVENT_LIST_KEY,
+      expect.any(String)
+    );
+
+    const trackEvents = mockRequest.history.post.filter(
+      (req) => req.url === '/anonymoususer/events/session'
+    );
+
+    expect(trackEvents.length > 0).toBe(true);
+
+    trackEvents.forEach((req) => {
+      const requestData = JSON.parse(String(req?.data));
+
+      expect(requestData).toHaveProperty('user');
+      expect(requestData.user).toHaveProperty(
+        'dataFields',
+        userDataMatched.dataFields
+      );
+      expect(requestData.user.dataFields).toHaveProperty(
+        'furniture',
+        userDataMatched.dataFields.furniture
+      );
+    });
+
+    const trackEventsUserUpdate = mockRequest.history.post.filter(
+      (req) => req.url === '/users/update'
+    );
+    expect(trackEventsUserUpdate.length === 0).toBe(true);
+  });
+});
diff --git a/src/anonymousUserTracking/tests/validateCustomEventUserUpdateAPI.test.ts b/src/anonymousUserTracking/tests/validateCustomEventUserUpdateAPI.test.ts
new file mode 100644
index 00000000..c8e625dd
--- /dev/null
+++ b/src/anonymousUserTracking/tests/validateCustomEventUserUpdateAPI.test.ts
@@ -0,0 +1,427 @@
+import MockAdapter from 'axios-mock-adapter';
+import { baseAxiosRequest } from '../../request';
+import {
+  SHARED_PREFS_ANON_SESSIONS,
+  SHARED_PREFS_EVENT_LIST_KEY,
+  SHARED_PREFS_CRITERIA,
+  ENDPOINT_MERGE_USER,
+  ENDPOINT_TRACK_ANON_SESSION,
+  GET_CRITERIA_PATH,
+  GETMESSAGES_PATH,
+  SHARED_PREF_ANON_USAGE_TRACKED
+} from '../../constants';
+import { track } from '../../events';
+import { initializeWithConfig } from '../../authorization';
+import CriteriaCompletionChecker from '../criteriaCompletionChecker';
+import { updateUser } from '../../users';
+import {
+  CUSTOM_EVENT_API_TEST_CRITERIA,
+  USER_UPDATE_API_TEST_CRITERIA
+} from './constants';
+
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
+declare global {
+  function uuidv4(): string;
+  function getEmail(): string;
+  function getUserID(): string;
+  function setUserID(): string;
+}
+
+// SUCCESS
+const eventDataMatched = {
+  eventName: 'animal-found',
+  dataFields: {
+    type: 'cat',
+    count: 6,
+    vaccinated: true
+  },
+  createNewFields: true,
+  eventType: 'customEvent'
+};
+
+// FAIL
+const eventData = {
+  eventName: 'animal-found',
+  dataFields: {
+    type: 'cat',
+    count: 6,
+    vaccinated: true
+  },
+  type: 'cat',
+  count: 6,
+  vaccinated: true,
+  createNewFields: true,
+  eventType: 'customEvent'
+};
+
+// SUCCESS
+const userDataMatched = {
+  dataFields: {
+    furniture: {
+      furnitureType: 'Sofa',
+      furnitureColor: 'White'
+    }
+  },
+  eventType: 'user'
+};
+
+// FAIL
+const userData = {
+  dataFields: {
+    furniture: {
+      furnitureType: 'Sofa',
+      furnitureColor: 'White'
+    }
+  },
+  furnitureType: 'Sofa',
+  furnitureColor: 'White',
+  eventType: 'user'
+};
+
+const initialAnonSessionInfo = {
+  itbl_anon_sessions: {
+    number_of_sessions: 1,
+    first_session: 123456789,
+    last_session: expect.any(Number)
+  }
+};
+
+const mockRequest = new MockAdapter(baseAxiosRequest);
+
+describe('validateCustomEventUserUpdateAPI', () => {
+  beforeAll(() => {
+    (global as any).localStorage = localStorageMock;
+    global.window = Object.create({ location: { hostname: 'google.com' } });
+    mockRequest.onGet(GETMESSAGES_PATH).reply(200, {
+      data: 'something'
+    });
+    mockRequest.onPost('/events/track').reply(200, {});
+    mockRequest.onPost('/users/update').reply(200, {});
+    mockRequest.onPost(ENDPOINT_MERGE_USER).reply(200, {});
+    mockRequest.onGet(GET_CRITERIA_PATH).reply(200, {});
+    mockRequest.onPost(ENDPOINT_TRACK_ANON_SESSION).reply(200, {});
+  });
+
+  beforeEach(() => {
+    mockRequest.reset();
+    mockRequest.resetHistory();
+    mockRequest.onGet(GETMESSAGES_PATH).reply(200, {
+      data: 'something'
+    });
+    mockRequest.onPost('/events/track').reply(200, {});
+    mockRequest.onPost('/users/update').reply(200, {});
+    mockRequest.onPost(ENDPOINT_MERGE_USER).reply(200, {});
+    mockRequest.onGet(GET_CRITERIA_PATH).reply(200, {});
+    mockRequest.onPost(ENDPOINT_TRACK_ANON_SESSION).reply(200, {});
+    jest.resetAllMocks();
+    jest.useFakeTimers();
+  });
+
+  it('should not have unnecessary extra nesting when locally stored user update fields are sent to server', async () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            ...userDataMatched.dataFields,
+            eventType: userDataMatched.eventType
+          }
+        ]);
+      }
+      if (key === SHARED_PREFS_CRITERIA) {
+        return JSON.stringify(USER_UPDATE_API_TEST_CRITERIA);
+      }
+      if (key === SHARED_PREFS_ANON_SESSIONS) {
+        return JSON.stringify(initialAnonSessionInfo);
+      }
+      if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+        return 'true';
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const localStoredCriteriaSets = localStorage.getItem(SHARED_PREFS_CRITERIA);
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(localStoredCriteriaSets!);
+    expect(result).toEqual('6');
+
+    const { setUserID, logout } = initializeWithConfig({
+      authToken: '123',
+      configOptions: { enableAnonActivation: true }
+    });
+    logout(); // logout to remove logged in users before this test
+
+    try {
+      await updateUser();
+    } catch (e) {
+      console.log('');
+    }
+    expect(localStorage.setItem).toHaveBeenCalledWith(
+      SHARED_PREFS_EVENT_LIST_KEY,
+      expect.any(String)
+    );
+    await setUserID('testuser123');
+
+    const trackEvents = mockRequest.history.post.filter(
+      (req) => req.url === '/users/update'
+    );
+
+    expect(trackEvents.length > 0).toBe(true);
+
+    trackEvents.forEach((req) => {
+      const requestData = JSON.parse(String(req?.data));
+
+      expect(requestData).toHaveProperty(
+        'dataFields',
+        userDataMatched.dataFields
+      );
+      expect(requestData.dataFields).toHaveProperty(
+        'furniture',
+        userDataMatched.dataFields.furniture
+      );
+      expect(requestData.dataFields).toHaveProperty(
+        'furniture.furnitureType',
+        userDataMatched.dataFields.furniture.furnitureType
+      );
+      expect(requestData.dataFields).toHaveProperty(
+        'furniture.furnitureColor',
+        userDataMatched.dataFields.furniture.furnitureColor
+      );
+
+      expect(requestData).not.toHaveProperty('furniture');
+      expect(requestData).not.toHaveProperty('furnitureType');
+      expect(requestData).not.toHaveProperty('furnitureColor');
+      expect(requestData).not.toHaveProperty('furniture.furnitureType');
+      expect(requestData).not.toHaveProperty('furniture.furnitureColor');
+    });
+  });
+
+  it('should not have unnecessary extra nesting when locally stored user update fields are sent to server - Fail', async () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([
+          {
+            ...userData,
+            ...userData.dataFields,
+            eventType: userData.eventType
+          }
+        ]);
+      }
+      if (key === SHARED_PREFS_CRITERIA) {
+        return JSON.stringify(USER_UPDATE_API_TEST_CRITERIA);
+      }
+      if (key === SHARED_PREFS_ANON_SESSIONS) {
+        return JSON.stringify(initialAnonSessionInfo);
+      }
+      if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+        return 'true';
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const localStoredCriteriaSets = localStorage.getItem(SHARED_PREFS_CRITERIA);
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(localStoredCriteriaSets!);
+    expect(result).toEqual('6');
+
+    const { setUserID, logout } = initializeWithConfig({
+      authToken: '123',
+      configOptions: { enableAnonActivation: true }
+    });
+    logout(); // logout to remove logged in users before this test
+
+    try {
+      await updateUser();
+    } catch (e) {
+      console.log('');
+    }
+    expect(localStorage.setItem).toHaveBeenCalledWith(
+      SHARED_PREFS_EVENT_LIST_KEY,
+      expect.any(String)
+    );
+    await setUserID('testuser123');
+
+    const trackEvents = mockRequest.history.post.filter(
+      (req) => req.url === '/users/update'
+    );
+
+    expect(trackEvents.length > 0).toBe(true);
+
+    trackEvents.forEach((req) => {
+      const requestData = JSON.parse(String(req?.data));
+
+      expect(requestData).toHaveProperty('dataFields');
+      expect(requestData.dataFields).toHaveProperty('furniture');
+      expect(requestData.dataFields).toHaveProperty('furniture.furnitureType');
+      expect(requestData.dataFields).toHaveProperty('furniture.furnitureColor');
+
+      expect(requestData).not.toHaveProperty('furniture');
+      expect(requestData).not.toHaveProperty('furniture.furnitureType');
+      expect(requestData).not.toHaveProperty('furniture.furnitureColor');
+      expect(requestData.dataFields).toHaveProperty('furnitureType');
+      expect(requestData.dataFields).toHaveProperty('furnitureColor');
+    });
+  });
+
+  it('should not have unnecessary extra nesting when locally stored custom event fields are sent to server', async () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([eventDataMatched]);
+      }
+      if (key === SHARED_PREFS_CRITERIA) {
+        return JSON.stringify(CUSTOM_EVENT_API_TEST_CRITERIA);
+      }
+      if (key === SHARED_PREFS_ANON_SESSIONS) {
+        return JSON.stringify(initialAnonSessionInfo);
+      }
+      if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+        return 'true';
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const localStoredCriteriaSets = localStorage.getItem(SHARED_PREFS_CRITERIA);
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+
+    const result = checker.getMatchedCriteria(localStoredCriteriaSets!);
+
+    expect(result).toEqual('6');
+
+    const { setUserID, logout } = initializeWithConfig({
+      authToken: '123',
+      configOptions: { enableAnonActivation: true }
+    });
+    logout(); // logout to remove logged in users before this test
+
+    try {
+      await track(eventDataMatched);
+    } catch (e) {
+      console.log('');
+    }
+    expect(localStorage.setItem).toHaveBeenCalledWith(
+      SHARED_PREFS_EVENT_LIST_KEY,
+      expect.any(String)
+    );
+    await setUserID('testuser123');
+
+    const trackEvents = mockRequest.history.post.filter(
+      (req) => req.url === '/events/track'
+    );
+
+    trackEvents.forEach((req) => {
+      const requestData = JSON.parse(String(req?.data));
+
+      expect(requestData).toHaveProperty(
+        'eventName',
+        eventDataMatched.eventName
+      );
+      expect(requestData).toHaveProperty(
+        'dataFields',
+        eventDataMatched.dataFields
+      );
+
+      expect(requestData).not.toHaveProperty(eventDataMatched.eventName);
+      expect(requestData).not.toHaveProperty('type');
+      expect(requestData).not.toHaveProperty('count');
+      expect(requestData).not.toHaveProperty('vaccinated');
+      expect(requestData).not.toHaveProperty('animal-found.type');
+      expect(requestData).not.toHaveProperty('animal-found.count');
+      expect(requestData).not.toHaveProperty('animal-found.vaccinated');
+    });
+  });
+
+  it('should not have unnecessary extra nesting when locally stored custom event fields are sent to server - Fail', async () => {
+    (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+      if (key === SHARED_PREFS_EVENT_LIST_KEY) {
+        return JSON.stringify([eventData]);
+      }
+      if (key === SHARED_PREFS_CRITERIA) {
+        return JSON.stringify(CUSTOM_EVENT_API_TEST_CRITERIA);
+      }
+      if (key === SHARED_PREFS_ANON_SESSIONS) {
+        return JSON.stringify(initialAnonSessionInfo);
+      }
+      if (key === SHARED_PREF_ANON_USAGE_TRACKED) {
+        return 'true';
+      }
+      return null;
+    });
+
+    const localStoredEventList = localStorage.getItem(
+      SHARED_PREFS_EVENT_LIST_KEY
+    );
+
+    const localStoredCriteriaSets = localStorage.getItem(SHARED_PREFS_CRITERIA);
+
+    const checker = new CriteriaCompletionChecker(
+      localStoredEventList === null ? '' : localStoredEventList
+    );
+    const result = checker.getMatchedCriteria(
+      JSON.stringify(localStoredCriteriaSets)
+    );
+    expect(result).toBeNull();
+
+    const { setUserID, logout } = initializeWithConfig({
+      authToken: '123',
+      configOptions: { enableAnonActivation: true }
+    });
+    logout(); // logout to remove logged in users before this test
+
+    try {
+      await track(eventData);
+    } catch (e) {
+      console.log('');
+    }
+    expect(localStorage.setItem).toHaveBeenCalledWith(
+      SHARED_PREFS_EVENT_LIST_KEY,
+      expect.any(String)
+    );
+    await setUserID('testuser123');
+
+    const trackEvents = mockRequest.history.post.filter(
+      (req) => req.url === '/events/track'
+    );
+
+    trackEvents.forEach((req) => {
+      const requestData = JSON.parse(String(req?.data));
+
+      expect(requestData).toHaveProperty('eventName', eventData.eventName);
+      expect(requestData).toHaveProperty('dataFields', eventData.dataFields);
+
+      expect(requestData).not.toHaveProperty(eventData.eventName);
+      expect(requestData).toHaveProperty('type');
+      expect(requestData).toHaveProperty('count');
+      expect(requestData).toHaveProperty('vaccinated');
+      expect(requestData).not.toHaveProperty('animal-found.type');
+      expect(requestData).not.toHaveProperty('animal-found.count');
+      expect(requestData).not.toHaveProperty('animal-found.vaccinated');
+    });
+  });
+});
diff --git a/src/authorization/authorization.test.ts b/src/authorization/authorization.test.ts
index 84614faa..54428994 100644
--- a/src/authorization/authorization.test.ts
+++ b/src/authorization/authorization.test.ts
@@ -1,19 +1,25 @@
 import axios from 'axios';
 import MockAdapter from 'axios-mock-adapter';
-import { initialize } from './authorization';
+import { initialize, setTypeOfAuthForTestingOnly } from './authorization';
 import { baseAxiosRequest } from '../request';
 import { getInAppMessages } from '../inapp';
 import { track, trackInAppClose } from '../events';
 import { updateSubscriptions, updateUser, updateUserEmail } from '../users';
 import { trackPurchase, updateCart } from '../commerce';
-import { GETMESSAGES_PATH } from '../constants';
-
-let mockRequest: any = null;
+import {
+  GETMESSAGES_PATH,
+  INITIALIZE_ERROR,
+  SHARED_PREF_USER_TOKEN
+} from '../constants';
 
 const localStorageMock = {
-  setItem: jest.fn()
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
 };
 
+let mockRequest: any = null;
+
 /*
   decoded payload is:
 
@@ -29,6 +35,7 @@ const MOCK_JWT_KEY_WITH_ONE_MINUTE_EXPIRY =
   'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3RAdGVzdC5jb20iLCJleHAiOjE2Nzk0ODMyOTEsImlhdCI6MTY3OTQ4MzIzMX0.APaQAYy-lTE0o8rbR6b6-28eCICq36SQMBXmeZAvk1k';
 describe('API Key Interceptors', () => {
   beforeAll(() => {
+    (global as any).localStorage = localStorageMock;
     mockRequest = new MockAdapter(baseAxiosRequest);
     mockRequest.onGet(GETMESSAGES_PATH).reply(200, {
       data: 'something'
@@ -38,6 +45,8 @@ describe('API Key Interceptors', () => {
   });
 
   beforeEach(() => {
+    setTypeOfAuthForTestingOnly('userID');
+
     mockRequest.onPost('/users/update').reply(200, {
       data: 'something'
     });
@@ -97,7 +106,12 @@ describe('API Key Interceptors', () => {
       const { setEmail } = initialize('123', () =>
         Promise.resolve(MOCK_JWT_KEY)
       );
-      (global as any).localStorage = localStorageMock;
+      (localStorage.getItem as jest.Mock).mockImplementation((key) => {
+        if (key === SHARED_PREF_USER_TOKEN) {
+          return MOCK_JWT_KEY;
+        }
+        return null;
+      });
       await setEmail('hello@gmail.com');
 
       const response = await getInAppMessages({
@@ -105,7 +119,7 @@ describe('API Key Interceptors', () => {
         packageName: 'my-lil-website'
       });
       expect(response.config.headers['Api-Key']).toBe('123');
-      expect(response.config.headers['Authorization']).toBe(
+      expect(response.config.headers.Authorization).toBe(
         `Bearer ${MOCK_JWT_KEY}`
       );
     });
@@ -122,7 +136,7 @@ describe('API Key Interceptors', () => {
         packageName: 'my-lil-website'
       });
       expect(response.config.headers['Api-Key']).toBe('123');
-      expect(response.config.headers['Authorization']).toBe(
+      expect(response.config.headers.Authorization).toBe(
         `Bearer ${MOCK_JWT_KEY}`
       );
     });
@@ -227,8 +241,8 @@ describe('API Key Interceptors', () => {
       await updateUserEmail('helloworld@gmail.com');
 
       jest.advanceTimersByTime(60000 * 4.1);
-      /* 
-        called once originally, a second time after the email was changed, 
+      /*
+        called once originally, a second time after the email was changed,
         and a third after the JWT was about to expire
       */
       expect(mockGenerateJWT).toHaveBeenCalledTimes(3);
@@ -276,8 +290,8 @@ describe('API Key Interceptors', () => {
       });
 
       jest.advanceTimersByTime(60000 * 4.1);
-      /* 
-        called once originally, a second time after the email was changed, 
+      /*
+        called once originally, a second time after the email was changed,
         and a third after the JWT was about to expire
       */
       expect(mockGenerateJWT).toHaveBeenCalledTimes(3);
@@ -310,8 +324,8 @@ describe('API Key Interceptors', () => {
       });
 
       jest.advanceTimersByTime(60000 * 4.1);
-      /* 
-        called once originally, a second time after the email was changed, 
+      /*
+        called once originally, a second time after the email was changed,
         and a third after the JWT was about to expire
       */
       expect(mockGenerateJWT).toHaveBeenCalledTimes(3);
@@ -339,6 +353,8 @@ describe('API Key Interceptors', () => {
 
 describe('User Identification', () => {
   beforeEach(() => {
+    setTypeOfAuthForTestingOnly('userID');
+
     /* clear any interceptors already configured */
     [
       ...Array(
@@ -351,6 +367,7 @@ describe('User Identification', () => {
 
   describe('non-JWT auth', () => {
     beforeAll(() => {
+      (global as any).localStorage = localStorageMock;
       mockRequest = new MockAdapter(baseAxiosRequest);
 
       mockRequest.onPost('/users/update').reply(200, {});
@@ -363,14 +380,17 @@ describe('User Identification', () => {
     describe('logout', () => {
       it('logout method removes the email field from requests', async () => {
         const { logout, setEmail } = initialize('123');
-        setEmail('hello@gmail.com');
+        await setEmail('hello@gmail.com');
         logout();
 
-        const response = await getInAppMessages({
-          count: 10,
-          packageName: 'my-lil-website'
-        });
-        expect(response.config.params.email).toBeUndefined();
+        try {
+          await getInAppMessages({
+            count: 10,
+            packageName: 'my-lil-website'
+          });
+        } catch (e) {
+          expect(e).toStrictEqual(INITIALIZE_ERROR);
+        }
       });
 
       it('logout method removes the userId field from requests', async () => {
@@ -379,32 +399,34 @@ describe('User Identification', () => {
         await setUserID('hello@gmail.com');
         logout();
 
-        const response = await getInAppMessages({
-          count: 10,
-          packageName: 'my-lil-website'
-        });
-        expect(response.config.params.userId).toBeUndefined();
+        try {
+          await getInAppMessages({
+            count: 10,
+            packageName: 'my-lil-website'
+          });
+        } catch (e) {
+          expect(e).toStrictEqual(INITIALIZE_ERROR);
+        }
       });
     });
 
     describe('setEmail', () => {
       it('adds email param to endpoint that need an email as a param', async () => {
         const { setEmail } = initialize('123');
-        setEmail('hello@gmail.com');
+        await setEmail('hello@gmail.com');
 
         const response = await getInAppMessages({
           count: 10,
           packageName: 'my-lil-website'
         });
-
         expect(response.config.params.email).toBe('hello@gmail.com');
       });
 
       it('clears any previous interceptors if called twice', async () => {
         const spy = jest.spyOn(baseAxiosRequest.interceptors.request, 'eject');
         const { setEmail } = initialize('123');
-        setEmail('hello@gmail.com');
-        setEmail('new@gmail.com');
+        await setEmail('hello@gmail.com');
+        await setEmail('new@gmail.com');
 
         const response = await getInAppMessages({
           count: 10,
@@ -421,7 +443,7 @@ describe('User Identification', () => {
 
       it('adds email body to endpoint that need an email as a body', async () => {
         const { setEmail } = initialize('123');
-        setEmail('hello@gmail.com');
+        await setEmail('hello@gmail.com');
 
         mockRequest.onPost('/events/trackInAppClose').reply(200, {
           data: 'something'
@@ -450,7 +472,7 @@ describe('User Identification', () => {
         expect(JSON.parse(subsResponse.config.data).email).toBe(
           'hello@gmail.com'
         );
-        expect(JSON.parse(userResponse.config.data).email).toBe(
+        expect(JSON.parse(userResponse && userResponse.config.data).email).toBe(
           'hello@gmail.com'
         );
         expect(JSON.parse(trackResponse.config.data).email).toBe(
@@ -460,7 +482,7 @@ describe('User Identification', () => {
 
       it('adds currentEmail body to endpoint that need an currentEmail as a body', async () => {
         const { setEmail } = initialize('123');
-        setEmail('hello@gmail.com');
+        await setEmail('hello@gmail.com');
 
         mockRequest.onPost('/users/updateEmail').reply(200, {
           data: 'something'
@@ -475,7 +497,7 @@ describe('User Identification', () => {
 
       it('should add user.email param to endpoints that need it', async () => {
         const { setEmail } = initialize('123');
-        setEmail('hello@gmail.com');
+        await setEmail('hello@gmail.com');
 
         mockRequest.onPost('/commerce/updateCart').reply(200, {
           data: 'something'
@@ -496,7 +518,7 @@ describe('User Identification', () => {
 
       it('adds no email body or header information to unrelated endpoints', async () => {
         const { setEmail } = initialize('123');
-        setEmail('hello@gmail.com');
+        await setEmail('hello@gmail.com');
 
         mockRequest.onPost('/users/hello').reply(200, {
           data: 'something'
@@ -518,7 +540,7 @@ describe('User Identification', () => {
       it('should overwrite user ID set by setUserID', async () => {
         const { setEmail, setUserID } = initialize('123');
         await setUserID('999');
-        setEmail('hello@gmail.com');
+        await setEmail('hello@gmail.com');
 
         const response = await getInAppMessages({
           count: 10,
@@ -601,7 +623,9 @@ describe('User Identification', () => {
 
         expect(JSON.parse(closeResponse.config.data).userId).toBe('999');
         expect(JSON.parse(subsResponse.config.data).userId).toBe('999');
-        expect(JSON.parse(userResponse.config.data).userId).toBe('999');
+        expect(
+          JSON.parse(userResponse && userResponse.config.data).userId
+        ).toBe('999');
         expect(JSON.parse(trackResponse.config.data).userId).toBe('999');
       });
 
@@ -657,7 +681,7 @@ describe('User Identification', () => {
 
       it('should overwrite email set by setEmail', async () => {
         const { setEmail, setUserID } = initialize('123');
-        setEmail('hello@gmail.com');
+        await setEmail('hello@gmail.com');
         await setUserID('999');
 
         const response = await getInAppMessages({
@@ -667,19 +691,6 @@ describe('User Identification', () => {
         expect(response.config.params.email).toBeUndefined();
         expect(response.config.params.userId).toBe('999');
       });
-
-      it('should try /users/update 0 times if request to create a user fails', async () => {
-        mockRequest.onPost('/users/update').reply(400, {});
-
-        const { setUserID } = initialize('123');
-        await setUserID('999');
-
-        expect(
-          mockRequest.history.post.filter(
-            (e: any) => !!e.url?.match(/users\/update/gim)
-          ).length
-        ).toBe(1);
-      });
     });
   });
 
@@ -702,11 +713,14 @@ describe('User Identification', () => {
         await setEmail('hello@gmail.com');
         logout();
 
-        const response = await getInAppMessages({
-          count: 10,
-          packageName: 'my-lil-website'
-        });
-        expect(response.config.params.email).toBeUndefined();
+        try {
+          await getInAppMessages({
+            count: 10,
+            packageName: 'my-lil-website'
+          });
+        } catch (e) {
+          expect(e).toStrictEqual(INITIALIZE_ERROR);
+        }
       });
 
       it('logout method removes the userId field from requests', async () => {
@@ -716,11 +730,14 @@ describe('User Identification', () => {
         await setUserID('hello@gmail.com');
         logout();
 
-        const response = await getInAppMessages({
-          count: 10,
-          packageName: 'my-lil-website'
-        });
-        expect(response.config.params.userId).toBeUndefined();
+        try {
+          await getInAppMessages({
+            count: 10,
+            packageName: 'my-lil-website'
+          });
+        } catch (e) {
+          expect(e).toStrictEqual(INITIALIZE_ERROR);
+        }
       });
     });
 
@@ -793,7 +810,7 @@ describe('User Identification', () => {
         expect(JSON.parse(subsResponse.config.data).email).toBe(
           'hello@gmail.com'
         );
-        expect(JSON.parse(userResponse.config.data).email).toBe(
+        expect(JSON.parse(userResponse && userResponse.config.data).email).toBe(
           'hello@gmail.com'
         );
         expect(JSON.parse(trackResponse.config.data).email).toBe(
@@ -960,7 +977,9 @@ describe('User Identification', () => {
 
         expect(JSON.parse(closeResponse.config.data).userId).toBe('999');
         expect(JSON.parse(subsResponse.config.data).userId).toBe('999');
-        expect(JSON.parse(userResponse.config.data).userId).toBe('999');
+        expect(
+          JSON.parse(userResponse && userResponse.config.data).userId
+        ).toBe('999');
         expect(JSON.parse(trackResponse.config.data).userId).toBe('999');
       });
 
@@ -1069,7 +1088,7 @@ describe('User Identification', () => {
           packageName: 'my-lil-website'
         });
         expect(response.config.headers['Api-Key']).toBe('123');
-        expect(response.config.headers['Authorization']).toBe(
+        expect(response.config.headers.Authorization).toBe(
           `Bearer ${MOCK_JWT_KEY}`
         );
       });
@@ -1086,7 +1105,7 @@ describe('User Identification', () => {
           packageName: 'my-lil-website'
         });
         expect(response.config.headers['Api-Key']).toBe('123');
-        expect(response.config.headers['Authorization']).toBe(
+        expect(response.config.headers.Authorization).toBe(
           `Bearer ${MOCK_JWT_KEY}`
         );
       });
@@ -1100,7 +1119,6 @@ describe('User Identification', () => {
           .mockReturnValue(Promise.resolve(MOCK_JWT_KEY));
         const { refreshJwtToken } = initialize('123', mockGenerateJWT);
         await refreshJwtToken('hello@gmail.com');
-
         expect(mockGenerateJWT).toHaveBeenCalledTimes(1);
         jest.advanceTimersByTime(60000 * 4.1);
         expect(mockGenerateJWT).toHaveBeenCalledTimes(2);
diff --git a/src/authorization/authorization.ts b/src/authorization/authorization.ts
index 109bf78a..c579a977 100644
--- a/src/authorization/authorization.ts
+++ b/src/authorization/authorization.ts
@@ -1,17 +1,16 @@
 /* eslint-disable */
 import axios from 'axios';
 import { baseAxiosRequest } from '../request';
-import { updateUser } from '../users';
-import { clearMessages } from '../inapp';
+import { clearMessages } from 'src/inapp/inapp';
 import {
   IS_PRODUCTION,
-  RETRY_USER_ATTEMPTS,
   STATIC_HEADERS,
-  SHARED_PREF_USER_ID,
-  SHARED_PREF_EMAIL,
+  SHARED_PREF_ANON_USER_ID,
   ENDPOINTS,
-  RouteConfig
-} from '../constants';
+  RouteConfig,
+  SHARED_PREF_ANON_USAGE_TRACKED,
+  SHARED_PREFS_CRITERIA
+} from 'src/constants';
 import {
   cancelAxiosRequestAndMakeFetch,
   getEpochDifferenceInMS,
@@ -21,39 +20,300 @@ import {
   validateTokenTime,
   isEmail
 } from './utils';
-import { Options, config } from '../utils/config';
+import { AnonymousUserMerge } from 'src/anonymousUserTracking/anonymousUserMerge';
+import {
+  AnonymousUserEventManager,
+  isAnonymousUsageTracked,
+  registerAnonUserIdSetter
+} from 'src/anonymousUserTracking/anonymousUserEventManager';
+import { IdentityResolution, Options, config } from 'src/utils/config';
+import { getTypeOfAuth, setTypeOfAuth, TypeOfAuth } from 'src/utils/typeOfAuth';
+import AuthorizationToken from 'src/utils/authorizationToken';
 
 const MAX_TIMEOUT = ONE_DAY;
+let authIdentifier: null | string = null;
+let userInterceptor: number | null = null;
+let apiKey: null | string = null;
+let generateJWTGlobal: any = null;
+const anonUserManager = new AnonymousUserEventManager();
 
 export interface GenerateJWTPayload {
   email?: string;
   userID?: string;
 }
 
+const doesRequestUrlContain = (routeConfig: RouteConfig) =>
+  Object.entries(ENDPOINTS).some(
+    (entry) =>
+      routeConfig.route === entry[1].route &&
+      routeConfig.body === entry[1].body &&
+      routeConfig.current === entry[1].current &&
+      routeConfig.nestedUser === entry[1].nestedUser
+  );
 export interface WithJWT {
   clearRefresh: () => void;
-  setEmail: (email: string) => Promise<string>;
-  setUserID: (userId: string) => Promise<string>;
+  setEmail: (email: string, identityResolution?: IdentityResolution) => Promise<string>;
+  setUserID: (userId: string, identityResolution?: IdentityResolution) => Promise<string>;
   logout: () => void;
   refreshJwtToken: (authTypes: string) => Promise<string>;
+  setVisitorUsageTracked: (consent: boolean) => void;
+  clearVisitorEventsAndUserData: () => void;
 }
 
 export interface WithoutJWT {
   setNewAuthToken: (newToken?: string) => void;
   clearAuthToken: () => void;
-  setEmail: (email: string) => void;
-  setUserID: (userId: string) => Promise<void>;
+  setEmail: (email: string, identityResolution?: IdentityResolution) => Promise<void>;
+  setUserID: (userId: string, identityResolution?: IdentityResolution) => Promise<void>;
   logout: () => void;
+  setVisitorUsageTracked: (consent: boolean) => void;
+  clearVisitorEventsAndUserData: () => void;
 }
 
-const doesRequestUrlContain = (routeConfig: RouteConfig) =>
-  Object.entries(ENDPOINTS).some(
-    (entry) =>
-      routeConfig.route === entry[1].route &&
-      routeConfig.body === entry[1].body &&
-      routeConfig.current === entry[1].current &&
-      routeConfig.nestedUser === entry[1].nestedUser
-  );
+export const setAnonUserId = async (userId: string) => {
+  const anonymousUsageTracked = isAnonymousUsageTracked();
+
+  if (!anonymousUsageTracked) return;
+
+  let token: null | string = null;
+  if (generateJWTGlobal) {
+    token = await generateJWTGlobal({ userID: userId });
+  }
+
+  if (token) {
+    const authorizationToken = new AuthorizationToken();
+    authorizationToken.setToken(token);
+  }
+
+  baseAxiosRequest.interceptors.request.use((config) => {
+    config.headers.set('Api-Key', apiKey);
+
+    return config;
+  });
+  addUserIdToRequest(userId);
+  localStorage.setItem(SHARED_PREF_ANON_USER_ID, userId);
+};
+
+registerAnonUserIdSetter(setAnonUserId);
+
+const clearAnonymousUser = () => {
+  localStorage.removeItem(SHARED_PREF_ANON_USER_ID);
+};
+
+const getAnonUserId = () => {
+  if (config.getConfig('enableAnonActivation')) {
+    const anonUser = localStorage.getItem(SHARED_PREF_ANON_USER_ID);
+    return anonUser === undefined ? null : anonUser;
+  } else {
+    return null;
+  }
+};
+
+const initializeUserId = (userId: string) => {
+  addUserIdToRequest(userId);
+  clearAnonymousUser();
+};
+
+const addUserIdToRequest = (userId: string) => {
+  setTypeOfAuth('userID');
+  authIdentifier = userId;
+
+  if (typeof userInterceptor === 'number') {
+    baseAxiosRequest.interceptors.request.eject(userInterceptor);
+  }
+  /*
+    endpoints that use _userId_ payload prop in POST/PUT requests 
+  */
+  userInterceptor = baseAxiosRequest.interceptors.request.use((config) => {
+    if (
+      doesRequestUrlContain({
+        route: config?.url ?? '',
+        body: true,
+        current: true,
+        nestedUser: true
+      })
+    ) {
+      return {
+        ...config,
+        data: {
+          ...(config.data || {}),
+          currentUserId: userId
+        }
+      };
+    }
+
+    /*
+        endpoints that use _userId_ payload prop in POST/PUT requests 
+      */
+    if (
+      doesRequestUrlContain({
+        route: config?.url ?? '',
+        body: true,
+        current: false,
+        nestedUser: false
+      })
+    ) {
+      return {
+        ...config,
+        data: {
+          ...(config.data || {}),
+          userId
+        }
+      };
+    }
+
+    /*
+        endpoints that use _userId_ payload prop in POST/PUT requests nested in { user: {} }
+      */
+    if (
+      doesRequestUrlContain({
+        route: config?.url ?? '',
+        body: true,
+        current: false,
+        nestedUser: true
+      })
+    ) {
+      return {
+        ...config,
+        data: {
+          ...(config.data || {}),
+          user: {
+            ...(config.data.user || {}),
+            userId
+          }
+        }
+      };
+    }
+
+    /*
+        endpoints that use _userId_ query param in GET requests
+      */
+    if (
+      doesRequestUrlContain({
+        route: config?.url ?? '',
+        body: false,
+        current: false,
+        nestedUser: false
+      })
+    ) {
+      return {
+        ...config,
+        params: {
+          ...(config.params || {}),
+          userId
+        }
+      };
+    }
+
+    return config;
+  });
+};
+
+const initializeEmailUser = (email: string) => {
+  addEmailToRequest(email);
+  clearAnonymousUser();
+};
+
+const syncEvents = () => {
+  if (config.getConfig('enableAnonActivation')) {
+    anonUserManager.syncEvents();
+  }
+};
+
+const addEmailToRequest = (email: string) => {
+  setTypeOfAuth('email');
+  authIdentifier = email;
+
+  if (typeof userInterceptor === 'number') {
+    baseAxiosRequest.interceptors.request.eject(userInterceptor);
+  }
+  userInterceptor = baseAxiosRequest.interceptors.request.use((config) => {
+    /* 
+      endpoints that use _currentEmail_ payload prop in POST/PUT requests 
+    */
+    if (
+      doesRequestUrlContain({
+        route: config?.url ?? '',
+        body: true,
+        current: true,
+        nestedUser: true
+      })
+    ) {
+      return {
+        ...config,
+        data: {
+          ...(config.data || {}),
+          currentEmail: email
+        }
+      };
+    }
+
+    /*
+      endpoints that use _email_ payload prop in POST/PUT requests 
+    */
+    if (
+      doesRequestUrlContain({
+        route: config?.url ?? '',
+        body: true,
+        current: false,
+        nestedUser: false
+      })
+    ) {
+      return {
+        ...config,
+        data: {
+          ...(config.data || {}),
+          email
+        }
+      };
+    }
+
+    /*
+      endpoints that use _userId_ payload prop in POST/PUT requests nested in { user: {} }
+    */
+    if (
+      doesRequestUrlContain({
+        route: config?.url ?? '',
+        body: true,
+        current: false,
+        nestedUser: true
+      })
+    ) {
+      return {
+        ...config,
+        data: {
+          ...(config.data || {}),
+          user: {
+            ...(config.data.user || {}),
+            email
+          }
+        }
+      };
+    }
+
+    /*
+      endpoints that use _email_ query param in GET requests
+    */
+    if (
+      doesRequestUrlContain({
+        route: config?.url ?? '',
+        body: false,
+        current: false,
+        nestedUser: false
+      })
+    ) {
+      return {
+        ...config,
+        params: {
+          ...(config.params || {}),
+          email
+        }
+      };
+    }
+
+    return config;
+  });
+};
 
 export function initialize(
   authToken: string,
@@ -64,6 +324,8 @@ export function initialize(
   authToken: string,
   generateJWT?: (payload: GenerateJWTPayload) => Promise<string>
 ) {
+  apiKey = authToken;
+  generateJWTGlobal = generateJWT;
   const logLevel = config.getConfig('logLevel');
   if (!generateJWT && IS_PRODUCTION) {
     /* only let people use non-JWT mode if running the app locally */
@@ -74,36 +336,17 @@ export function initialize(
     }
     return;
   }
-
-  /*
+  /* 
     only set token interceptor if we're using a non-JWT key.
     Otherwise, we'll set it later once we generate the JWT
   */
-  let authInterceptor: number | null = generateJWT
-    ? null
-    : baseAxiosRequest.interceptors.request.use((config) => {
-        config.headers.set('Api-Key', authToken);
+  let authInterceptor: number | null =
+    baseAxiosRequest.interceptors.request.use((config) => {
+      config.headers.set('Api-Key', authToken);
 
-        return config;
-      });
-  let userInterceptor: number | null = null;
+      return config;
+    });
   let responseInterceptor: number | null = null;
-  /*
-    AKA did the user auth with their email (setEmail) or user ID (setUserID)
-
-    we're going to use this variable for one circumstance - when calling _updateUserEmail_.
-    Essentially, when we call the Iterable API to update a user's email address and we get a
-    successful 200 request, we're going to request a new JWT token, since it might need to
-    be re-signed with the new email address; however, if the customer code never authorized the
-    user with an email and instead a user ID, we'll just continue to sign the JWT with the user ID.
-
-    This is mainly just a quality-of-life feature, so that the customer's JWT generation code
-    doesn't _need_ to support email-signed JWTs if they don't want and purely want to issue the
-    tokens by user ID.
-  */
-  let typeOfAuth: null | 'email' | 'userID' = null;
-  /* this will be the literal user ID or email they choose to auth with */
-  let authIdentifier: null | string = null;
 
   /**
     method that sets a timer one minute before JWT expiration
@@ -153,97 +396,58 @@ export function initialize(
 
   const handleTokenExpiration = createTokenExpirationTimer();
 
-  const addEmailToRequest = (email: string) => {
-    userInterceptor = baseAxiosRequest.interceptors.request.use((config) => {
-      /*
-        endpoints that use _currentEmail_ payload prop in POST/PUT requests
-      */
-      if (
-        doesRequestUrlContain({
-          route: config?.url ?? '',
-          body: true,
-          current: true,
-          nestedUser: true
-        })
-      ) {
-        return {
-          ...config,
-          data: {
-            ...(config.data || {}),
-            currentEmail: email
-          }
-        };
-      }
-
-      /*
-        endpoints that use _email_ payload prop in POST/PUT requests
-      */
-      if (
-        doesRequestUrlContain({
-          route: config?.url ?? '',
-          body: true,
-          current: false,
-          nestedUser: false
-        })
-      ) {
-        return {
-          ...config,
-          data: {
-            ...(config.data || {}),
-            email
-          }
-        };
-      }
-
-      /*
-        endpoints that use _userId_ payload prop in POST/PUT requests nested in { user: {} }
-      */
-      if (
-        doesRequestUrlContain({
-          route: config?.url ?? '',
-          body: true,
-          current: false,
-          nestedUser: true
-        })
-      ) {
-        return {
-          ...config,
-          data: {
-            ...(config.data || {}),
-            user: {
-              ...(config.data.user || {}),
-              email
-            }
-          }
-        };
+  const enableAnonymousTracking = () => {
+    try {
+      if (config.getConfig('enableAnonActivation')) {
+        anonUserManager.getAnonCriteria();
+        anonUserManager.updateAnonSession();
+        const anonymousUserId = getAnonUserId();
+        if (anonymousUserId !== null) {
+          // This block will restore the anon userID from localstorage
+          setAnonUserId(anonymousUserId);
+        }
       }
+    } catch (error) {
+      console.warn(error);
+    }
+  };
 
-      /*
-        endpoints that use _email_ query param in GET requests
-      */
-
-      if (
-        doesRequestUrlContain({
-          route: config?.url ?? '',
-          body: false,
-          current: false,
-          nestedUser: false
-        })
-      ) {
-        return {
-          ...config,
-          params: {
-            ...(config.params || {}),
-            email
-          }
-        };
+  const tryMergeUser = async (
+    emailOrUserId: string,
+    isEmail: boolean,
+    merge?: boolean
+  ): Promise<boolean> => {
+    const typeOfAuth = getTypeOfAuth();
+    const enableAnonActivation = config.getConfig('enableAnonActivation');
+    const sourceUserIdOrEmail =
+      authIdentifier === null ? getAnonUserId() : authIdentifier;
+    const sourceUserId = typeOfAuth === 'email' ? null : sourceUserIdOrEmail;
+    const sourceEmail = typeOfAuth === 'email' ? sourceUserIdOrEmail : null;
+    const destinationUserId = isEmail ? null : emailOrUserId;
+    const destinationEmail = isEmail ? emailOrUserId : null;
+    // This function will try to merge if anon user exists
+    if (
+      (getAnonUserId() !== null || authIdentifier !== null) &&
+      merge &&
+      enableAnonActivation
+    ) {
+      const anonymousUserMerge = new AnonymousUserMerge();
+      try {
+        await anonymousUserMerge.mergeUser(
+          sourceUserId,
+          sourceEmail,
+          destinationUserId,
+          destinationEmail
+        );
+      } catch (error) {
+        return Promise.reject(`merging failed: ${error}`);
       }
-
-      return config;
-    });
+    }
+    return Promise.resolve(true); // promise resolves here because merging is not needed so we setUserID passed via dev
   };
 
   if (!generateJWT) {
+    enableAnonymousTracking();
     /* we want to set a normal non-JWT enabled API key */
     return {
       setNewAuthToken: (newToken: string) => {
@@ -265,151 +469,76 @@ export function initialize(
           baseAxiosRequest.interceptors.request.eject(authInterceptor);
         }
       },
-      setEmail: (email: string) => {
-        typeOfAuth = 'email';
-        authIdentifier = email;
-        localStorage.setItem(SHARED_PREF_EMAIL, email);
+      setEmail: async (
+        email: string,
+        identityResolution?: IdentityResolution
+      ) => {
         clearMessages();
-        if (typeof userInterceptor === 'number') {
-          baseAxiosRequest.interceptors.request.eject(userInterceptor);
+        try {
+          const identityResolutionConfig =
+            config.getConfig('identityResolution');
+          const merge =
+            identityResolution?.mergeOnAnonymousToKnown ||
+            identityResolutionConfig?.mergeOnAnonymousToKnown;
+          const replay =
+            identityResolution?.replayOnVisitorToKnown ||
+            identityResolutionConfig?.replayOnVisitorToKnown;
+
+          const result = await tryMergeUser(email, true, merge);
+          if (result) {
+            initializeEmailUser(email);
+            if (replay) {
+              syncEvents();
+            } else {
+              anonUserManager.removeAnonSessionCriteriaData();
+            }
+            return Promise.resolve();
+          }
+        } catch (error) {
+          // here we will not sync events but just bubble up error of merge
+          return Promise.reject(`merging failed: ${error}`);
         }
-
-        /*
-          endpoints that use _currentEmail_ payload prop in POST/PUT requests
-        */
-        addEmailToRequest(email);
       },
-      setUserID: async (userId: string) => {
-        typeOfAuth = 'userID';
-        authIdentifier = userId;
-        localStorage.setItem(SHARED_PREF_USER_ID, userId);
+      setUserID: async (
+        userId: string,
+        identityResolution?: IdentityResolution
+      ) => {
         clearMessages();
-
-        if (typeof userInterceptor === 'number') {
-          baseAxiosRequest.interceptors.request.eject(userInterceptor);
-        }
-
-        /*
-          endpoints that use _currentUserId payload prop in POST/PUT requests nested in { user: {} }
-        */
-        userInterceptor = baseAxiosRequest.interceptors.request.use(
-          (config) => {
-            if (
-              doesRequestUrlContain({
-                route: config?.url ?? '',
-                body: true,
-                current: true,
-                nestedUser: true
-              })
-            ) {
-              return {
-                ...config,
-                data: {
-                  ...(config.data || {}),
-                  currentUserId: userId
-                }
-              };
-            }
-
-            /*
-              endpoints that use _userId_ payload prop in POST/PUT requests
-            */
-            if (
-              doesRequestUrlContain({
-                route: config?.url ?? '',
-                body: true,
-                current: false,
-                nestedUser: false
-              })
-            ) {
-              return {
-                ...config,
-                data: {
-                  ...(config.data || {}),
-                  userId
-                }
-              };
-            }
-
-            /*
-              endpoints that use _userId_ payload prop in POST/PUT requests nested in { user: {} }
-            */
-            if (
-              doesRequestUrlContain({
-                route: config?.url ?? '',
-                body: true,
-                current: false,
-                nestedUser: true
-              })
-            ) {
-              return {
-                ...config,
-                data: {
-                  ...(config.data || {}),
-                  user: {
-                    ...(config.data.user || {}),
-                    userId
-                  }
-                }
-              };
-            }
-
-            /*
-              endpoints that use _userId_ query param in GET requests
-            */
-            if (
-              doesRequestUrlContain({
-                route: config?.url ?? '',
-                body: false,
-                current: false,
-                nestedUser: false
-              })
-            ) {
-              return {
-                ...config,
-                params: {
-                  ...(config.params || {}),
-                  userId
-                }
-              };
+        try {
+          const identityResolutionConfig =
+            config.getConfig('identityResolution');
+          const merge =
+            identityResolution?.mergeOnAnonymousToKnown ||
+            identityResolutionConfig?.mergeOnAnonymousToKnown;
+          const replay =
+            identityResolution?.replayOnVisitorToKnown ||
+            identityResolutionConfig?.replayOnVisitorToKnown;
+
+          const result = await tryMergeUser(userId, false, merge);
+          if (result) {
+            initializeUserId(userId);
+            if (replay) {
+              syncEvents();
+            } else {
+              anonUserManager.removeAnonSessionCriteriaData();
             }
-
-            return config;
+            return Promise.resolve();
           }
-        );
-
-        const tryUser = () => {
-          let createUserAttempts = 0;
-
-          return async function tryUserNTimes(): Promise<any> {
-            try {
-              return await updateUser({});
-            } catch (e) {
-              if (createUserAttempts < RETRY_USER_ATTEMPTS) {
-                createUserAttempts += 1;
-                return tryUserNTimes();
-              }
-
-              return Promise.reject(
-                `could not create user after ${createUserAttempts} tries`
-              );
-            }
-          };
-        };
-
-        try {
-          return await tryUser()();
-        } catch (e) {
-          /* failed to create a new user. Just silently resolve */
-          return Promise.resolve();
+        } catch (error) {
+          // here we will not sync events but just bubble up error of merge
+          return Promise.reject(`merging failed: ${error}`);
         }
       },
       logout: () => {
-        typeOfAuth = null;
+        anonUserManager.removeAnonSessionCriteriaData();
+        setTypeOfAuth(null);
         authIdentifier = null;
         /* clear fetched in-app messages */
         clearMessages();
 
+        const authorizationToken = new AuthorizationToken();
+        authorizationToken.clearToken();
+
         if (typeof authInterceptor === 'number') {
           /* stop adding auth token to requests */
           baseAxiosRequest.interceptors.request.eject(authInterceptor);
@@ -419,15 +548,48 @@ export function initialize(
           /* stop adding JWT to requests */
           baseAxiosRequest.interceptors.request.eject(userInterceptor);
         }
+      },
+      setVisitorUsageTracked: (consent: boolean) => {
+        /* if consent is true, we want to clear anon user data and start tracking from point forward */
+        if (consent) {
+          anonUserManager.removeAnonSessionCriteriaData();
+          localStorage.removeItem(SHARED_PREFS_CRITERIA);
+
+          localStorage.setItem(SHARED_PREF_ANON_USAGE_TRACKED, 'true');
+          enableAnonymousTracking();
+        } else {
+          /* if consent is false, we want to stop tracking and clear anon user data */
+          const anonymousUsageTracked = isAnonymousUsageTracked();
+          if (anonymousUsageTracked) {
+            anonUserManager.removeAnonSessionCriteriaData();
+
+            localStorage.removeItem(SHARED_PREFS_CRITERIA);
+            localStorage.removeItem(SHARED_PREF_ANON_USER_ID);
+            localStorage.removeItem(SHARED_PREF_ANON_USAGE_TRACKED);
+
+            setTypeOfAuth(null);
+            authIdentifier = null;
+            /* clear fetched in-app messages */
+            clearMessages();
+          }
+          localStorage.setItem(SHARED_PREF_ANON_USAGE_TRACKED, 'false');
+        }
+      },
+      clearVisitorEventsAndUserData: () => {
+        anonUserManager.removeAnonSessionCriteriaData();
+        clearAnonymousUser();
       }
     };
   }
 
+  const authorizationToken = new AuthorizationToken();
   /*
     We're using a JWT enabled API key
     callback is assumed to be some sort of GET /api/generate-jwt
   */
   const doRequest = (payload: { email?: string; userID?: string }) => {
+    authorizationToken.clearToken();
+
     /* clear any token interceptor if any exists */
     if (typeof authInterceptor === 'number') {
       baseAxiosRequest.interceptors.request.eject(authInterceptor);
@@ -439,6 +601,9 @@ export function initialize(
 
     return generateJWT(payload)
       .then((token) => {
+        const authorizationToken = new AuthorizationToken();
+        authorizationToken.setToken(token);
+
         /* set JWT token and auth token headers */
         authInterceptor = baseAxiosRequest.interceptors.request.use(
           (config) => {
@@ -467,7 +632,6 @@ export function initialize(
             }
 
             config.headers.set('Api-Key', authToken);
-            config.headers.set('Authorization', `Bearer ${token}`);
 
             return config;
           }
@@ -493,11 +657,14 @@ export function initialize(
                 const newEmail = JSON.parse(config.config.data)?.newEmail;
 
                 const payloadToPass =
-                  typeOfAuth === 'email'
+                  getTypeOfAuth() === 'email'
                     ? { email: newEmail }
                     : { userID: authIdentifier! };
 
                 return generateJWT(payloadToPass).then((newToken) => {
+                  const authorizationToken = new AuthorizationToken();
+                  authorizationToken.setToken(newToken);
+
                   /*
                     clear any existing interceptors that are adding user info
                     or API keys
@@ -543,7 +710,6 @@ export function initialize(
                       }
 
                       config.headers.set('Api-Key', authToken);
-                      config.headers.set('Authorization', `Bearer ${newToken}`);
 
                       return config;
                     }
@@ -590,6 +756,9 @@ export function initialize(
             if (error?.response?.status === 401) {
               return generateJWT(payload)
                 .then((newToken) => {
+                  const authorizationToken = new AuthorizationToken();
+                  authorizationToken.setToken(newToken);
+
                   if (authInterceptor) {
                     baseAxiosRequest.interceptors.request.eject(
                       authInterceptor
@@ -621,7 +790,6 @@ export function initialize(
                       }
 
                       config.headers.set('Api-Key', authToken);
-                      config.headers.set('Authorization', `Bearer ${newToken}`);
 
                       return config;
                     }
@@ -666,172 +834,118 @@ export function initialize(
         );
         return token;
       })
-      .catch((error: any) => {
+      .catch((error) => {
         /* clear interceptor */
+        const authorizationToken = new AuthorizationToken();
+        authorizationToken.clearToken();
+
         if (typeof authInterceptor === 'number') {
           baseAxiosRequest.interceptors.request.eject(authInterceptor);
         }
         return Promise.reject(error);
       });
   };
+
+  enableAnonymousTracking();
   return {
     clearRefresh: () => {
       /* this will just clear the existing timeout */
       handleTokenExpiration('');
     },
-    setEmail: (email: string) => {
-      typeOfAuth = 'email';
-      authIdentifier = email;
-      localStorage.setItem(SHARED_PREF_EMAIL, email);
+    setEmail: async (
+      email: string,
+      identityResolution?: IdentityResolution
+    ) => {
       /* clear previous user */
       clearMessages();
-      if (typeof userInterceptor === 'number') {
-        baseAxiosRequest.interceptors.request.eject(userInterceptor);
-      }
+      try {
+        const identityResolutionConfig = config.getConfig('identityResolution');
+        const merge =
+          identityResolution?.mergeOnAnonymousToKnown ||
+          identityResolutionConfig?.mergeOnAnonymousToKnown;
+        const replay =
+          identityResolution?.replayOnVisitorToKnown ||
+          identityResolutionConfig?.replayOnVisitorToKnown;
 
-      addEmailToRequest(email);
-
-      return doRequest({ email }).catch((e: any) => {
-        if (logLevel === 'verbose') {
-          console.warn(
-            'Could not generate JWT after calling setEmail. Please try calling setEmail again.'
-          );
+        try {
+          return doRequest({ email })
+            .then(async (token) => {
+              const result = await tryMergeUser(email, true, merge);
+              if (result) {
+                initializeEmailUser(email);
+                if (replay) {
+                  syncEvents();
+                } else {
+                  anonUserManager.removeAnonSessionCriteriaData();
+                }
+                return token;
+              }
+            })
+            .catch((e) => {
+              if (logLevel === 'verbose') {
+                console.warn(
+                  'Could not generate JWT after calling setEmail. Please try calling setEmail again.'
+                );
+              }
+              return Promise.reject(e);
+            });
+        } catch (e) {
+          /* failed to create a new user. Just silently resolve */
+          return Promise.resolve();
         }
-        return Promise.reject(e);
-      });
+      } catch (error) {
+        // here we will not sync events but just bubble up error of merge
+        return Promise.reject(`merging failed: ${error}`);
+      }
     },
-    setUserID: async (userId: string) => {
-      typeOfAuth = 'userID';
-      authIdentifier = userId;
-      localStorage.setItem(SHARED_PREF_USER_ID, userId);
+    setUserID: async (
+      userId: string,
+      identityResolution?: IdentityResolution
+    ) => {
       clearMessages();
+      try {
+        const identityResolutionConfig = config.getConfig('identityResolution');
+        const merge =
+          identityResolution?.mergeOnAnonymousToKnown ||
+          identityResolutionConfig?.mergeOnAnonymousToKnown;
+        const replay =
+          identityResolution?.replayOnVisitorToKnown ||
+          identityResolutionConfig?.replayOnVisitorToKnown;
 
-      if (typeof userInterceptor === 'number') {
-        baseAxiosRequest.interceptors.request.eject(userInterceptor);
-      }
-
-      /*
-        endpoints that use _currentUserId_ payload prop in POST/PUT requests nested in user object
-      */
-      userInterceptor = baseAxiosRequest.interceptors.request.use((config) => {
-        if (
-          doesRequestUrlContain({
-            route: config?.url ?? '',
-            body: true,
-            current: true,
-            nestedUser: true
-          })
-        ) {
-          return {
-            ...config,
-            data: {
-              ...(config.data || {}),
-              currentUserId: userId
-            }
-          };
-        }
-
-        /*
-          endpoints that use _serId_ payload prop in POST/PUT requests
-        */
-        if (
-          doesRequestUrlContain({
-            route: config?.url ?? '',
-            body: true,
-            current: false,
-            nestedUser: false
-          })
-        ) {
-          return {
-            ...config,
-            data: {
-              ...(config.data || {}),
-              userId
-            }
-          };
-        }
-
-        /*
-          endpoints that use _userId_ payload prop in POST/PUT requests nested in { user: {} }
-        */
-        if (
-          doesRequestUrlContain({
-            route: config?.url ?? '',
-            body: true,
-            current: false,
-            nestedUser: true
-          })
-        ) {
-          return {
-            ...config,
-            data: {
-              ...(config.data || {}),
-              user: {
-                ...(config.data.user || {}),
-                userId
+        try {
+          return doRequest({ userID: userId })
+            .then(async (token) => {
+              const result = await tryMergeUser(userId, false, merge);
+              if (result) {
+                initializeUserId(userId);
+                if (replay) {
+                  syncEvents();
+                } else {
+                  anonUserManager.removeAnonSessionCriteriaData();
+                }
+                return token;
               }
-            }
-          };
-        }
-
-        /*
-          endpoints that use _userId_ query param in GET requests
-        */
-        if (
-          doesRequestUrlContain({
-            route: config?.url ?? '',
-            body: false,
-            current: false,
-            nestedUser: false
-          })
-        ) {
-          return {
-            ...config,
-            params: {
-              ...(config.params || {}),
-              userId
-            }
-          };
+            })
+            .catch((e) => {
+              if (logLevel === 'verbose') {
+                console.warn(
+                  'Could not generate JWT after calling setUserID. Please try calling setUserID again.'
+                );
+              }
+              return Promise.reject(e);
+            });
+        } catch (e) {
+          /* failed to create a new user. Just silently resolve */
+          return Promise.resolve();
         }
-
-        return config;
-      });
-
-      const tryUser = () => {
-        let createUserAttempts = 0;
-
-        return async function tryUserNTimes(): Promise<any> {
-          try {
-            return await updateUser({});
-          } catch (e) {
-            if (createUserAttempts < RETRY_USER_ATTEMPTS) {
-              createUserAttempts += 1;
-              return tryUserNTimes();
-            }
-
-            return Promise.reject(
-              `could not create user after ${createUserAttempts} tries`
-            );
-          }
-        };
-      };
-
-      return doRequest({ userID: userId })
-        .then(async (token) => {
-          await tryUser()();
-          return token;
-        })
-        .catch((e: any) => {
-          if (logLevel === 'verbose') {
-            console.warn(
-              'Could not generate JWT after calling setUserID. Please try calling setUserID again.'
-            );
-          }
-          return Promise.reject(e);
-        });
+      } catch (error) {
+        // here we will not sync events but just bubble up error of merge
+        return Promise.reject(`merging failed: ${error}`);
+      }
     },
     logout: () => {
-      typeOfAuth = null;
+      anonUserManager.removeAnonSessionCriteriaData();
+      setTypeOfAuth(null);
       authIdentifier = null;
       /* clear fetched in-app messages */
       clearMessages();
@@ -839,6 +953,9 @@ export function initialize(
       /* this will just clear the existing timeout */
       handleTokenExpiration('');
 
+      const authorizationToken = new AuthorizationToken();
+      authorizationToken.clearToken();
+
       if (typeof authInterceptor === 'number') {
         /* stop adding auth token to requests */
         baseAxiosRequest.interceptors.request.eject(authInterceptor);
@@ -853,12 +970,42 @@ export function initialize(
       /* this will just clear the existing timeout */
       handleTokenExpiration('');
       const payloadToPass = { [isEmail(user) ? 'email' : 'userID']: user };
-      return doRequest(payloadToPass).catch((e: any) => {
+      return doRequest(payloadToPass).catch((e) => {
         if (logLevel === 'verbose') {
           console.warn(e);
           console.warn('Could not refresh JWT. Try Refresh the JWT again.');
         }
       });
+    },
+    setVisitorUsageTracked: (consent: boolean) => {
+      /* if consent is true, we want to clear anon user data and start tracking from point forward */
+      if (consent) {
+        anonUserManager.removeAnonSessionCriteriaData();
+        localStorage.removeItem(SHARED_PREFS_CRITERIA);
+
+        localStorage.setItem(SHARED_PREF_ANON_USAGE_TRACKED, 'true');
+        enableAnonymousTracking();
+      } else {
+        /* if consent is false, we want to stop tracking and clear anon user data */
+        const anonymousUsageTracked = isAnonymousUsageTracked();
+        if (anonymousUsageTracked) {
+          anonUserManager.removeAnonSessionCriteriaData();
+
+          localStorage.removeItem(SHARED_PREFS_CRITERIA);
+          localStorage.removeItem(SHARED_PREF_ANON_USER_ID);
+          localStorage.removeItem(SHARED_PREF_ANON_USAGE_TRACKED);
+
+          setTypeOfAuth(null);
+          authIdentifier = null;
+          /* clear fetched in-app messages */
+          clearMessages();
+        }
+        localStorage.setItem(SHARED_PREF_ANON_USAGE_TRACKED, 'false');
+      }
+    },
+    clearVisitorEventsAndUserData: () => {
+      anonUserManager.removeAnonSessionCriteriaData();
+      clearAnonymousUser();
     }
   };
 }
@@ -893,3 +1040,11 @@ export function initializeWithConfig(initializeParams: InitializeParams) {
     ? initialize(authToken, generateJWT)
     : initialize(authToken);
 }
+
+export function setTypeOfAuthForTestingOnly(authType: TypeOfAuth) {
+  if (!authType) {
+    setTypeOfAuth(null);
+  } else {
+    setTypeOfAuth(authType);
+  }
+}
diff --git a/src/commerce/commerce.test.ts b/src/commerce/commerce.test.ts
index 24645400..2de26ac6 100644
--- a/src/commerce/commerce.test.ts
+++ b/src/commerce/commerce.test.ts
@@ -3,10 +3,21 @@ import { baseAxiosRequest } from '../request';
 import { trackPurchase, updateCart } from './commerce';
 // import { SDK_VERSION, WEB_PLATFORM } from '../constants';
 import { createClientError } from '../utils/testUtils';
+import { setTypeOfAuthForTestingOnly } from '../authorization';
 
 const mockRequest = new MockAdapter(baseAxiosRequest);
 
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
 describe('Users Requests', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+    setTypeOfAuthForTestingOnly('email');
+  });
   it('should set params and return the correct payload for updateCart', async () => {
     mockRequest.onPost('/commerce/updateCart').reply(200, {
       msg: 'hello'
diff --git a/src/commerce/commerce.ts b/src/commerce/commerce.ts
index de8a6957..ec135bc7 100644
--- a/src/commerce/commerce.ts
+++ b/src/commerce/commerce.ts
@@ -1,9 +1,11 @@
 /* eslint-disable no-param-reassign */
-import { ENDPOINTS } from '../constants';
+import { ENDPOINTS, AUA_WARNING } from '../constants';
 import { baseIterableRequest } from '../request';
 import { TrackPurchaseRequestParams, UpdateCartRequestParams } from './types';
 import { IterableResponse } from '../types';
 import { updateCartSchema, trackPurchaseSchema } from './commerce.schema';
+import { AnonymousUserEventManager } from '../anonymousUserTracking/anonymousUserEventManager';
+import { canTrackAnonUser } from '../utils/commonFunctions';
 
 export const updateCart = (payload: UpdateCartRequestParams) => {
   /* a customer could potentially send these up if they're not using TypeScript */
@@ -11,6 +13,11 @@ export const updateCart = (payload: UpdateCartRequestParams) => {
     delete (payload as any).user.userId;
     delete (payload as any).user.email;
   }
+  if (canTrackAnonUser()) {
+    const anonymousUserEventManager = new AnonymousUserEventManager();
+    anonymousUserEventManager.trackAnonUpdateCart(payload);
+    return Promise.reject(AUA_WARNING);
+  }
 
   return baseIterableRequest<IterableResponse>({
     method: 'POST',
@@ -34,6 +41,11 @@ export const trackPurchase = (payload: TrackPurchaseRequestParams) => {
     delete (payload as any).user.userId;
     delete (payload as any).user.email;
   }
+  if (canTrackAnonUser()) {
+    const anonymousUserEventManager = new AnonymousUserEventManager();
+    anonymousUserEventManager.trackAnonPurchaseEvent(payload);
+    return Promise.reject(AUA_WARNING);
+  }
 
   return baseIterableRequest<IterableResponse>({
     method: 'POST',
diff --git a/src/constants.ts b/src/constants.ts
index 59646f0a..b68fa9f3 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -4,6 +4,9 @@ export const DISPLAY_INTERVAL_DEFAULT = 30000;
 /* how many times we try to create a new user when _setUserID_ is invoked */
 export const RETRY_USER_ATTEMPTS = 0;
 
+/* How many events can be stored in the local storage */
+export const DEFAULT_EVENT_THRESHOLD_LIMIT = 100;
+
 const IS_EU_ITERABLE_SERVICE = process.env.IS_EU_ITERABLE_SERVICE === 'true';
 
 export const dangerouslyAllowJsPopupExecution =
@@ -23,6 +26,9 @@ export const EU_ITERABLE_API = `https://${EU_ITERABLE_DOMAIN}/api`;
 export const BASE_URL = process.env.BASE_URL || ITERABLE_API_URL;
 
 export const GETMESSAGES_PATH = '/inApp/web/getMessages';
+export const GET_CRITERIA_PATH = '/anonymoususer/list';
+export const ENDPOINT_MERGE_USER = '/users/merge';
+export const ENDPOINT_TRACK_ANON_SESSION = '/anonymoususer/events/session';
 
 const GET_ENABLE_INAPP_CONSUME = () => {
   try {
@@ -273,3 +279,37 @@ export const ANIMATION_STYLESHEET = (
     transition: visibility 0s ${animationDuration}ms, opacity ${animationDuration}ms linear;
   }
 `;
+
+export const SHARED_PREFS_EVENT_TYPE = 'eventType';
+export const SHARED_PREFS_EVENT_LIST_KEY = 'itbl_event_list';
+export const SHARED_PREFS_CRITERIA = 'criteria';
+export const SHARED_PREFS_ANON_SESSIONS = 'itbl_anon_sessions';
+export const SHARED_PREF_ANON_USER_ID = 'anon_userId';
+export const SHARED_PREF_ANON_USAGE_TRACKED = 'itbl_anonymous_usage_tracked';
+export const SHARED_PREF_USER_TOKEN = 'itbl_auth_token';
+
+export const KEY_EVENT_NAME = 'eventName';
+export const KEY_CREATED_AT = 'createdAt';
+export const KEY_DATA_FIELDS = 'dataFields';
+export const KEY_CREATE_NEW_FIELDS = 'createNewFields';
+export const KEY_ITEMS = 'items';
+export const KEY_TOTAL = 'total';
+export const KEY_PREFER_USERID = 'preferUserId';
+export const DATA_REPLACE = 'dataReplace';
+
+export const TRACK_EVENT = 'customEvent';
+export const TRACK_PURCHASE = 'purchase';
+export const UPDATE_USER = 'user';
+export const TRACK_UPDATE_CART = 'cartUpdate';
+export const UPDATE_CART = 'updateCart';
+
+export const PURCHASE_ITEM = 'shoppingCartItems';
+export const UPDATECART_ITEM_PREFIX = 'updateCart.updatedShoppingCartItems.';
+export const PURCHASE_ITEM_PREFIX = `${PURCHASE_ITEM}.`;
+
+export const INITIALIZE_ERROR = new Error(
+  'Iterable SDK must be initialized with an API key and user email/userId before calling SDK methods'
+);
+export const AUA_WARNING = new Error(
+  'This event was stored locally because you have Anonymous User Activation enabled. If this was unintentional, please check your SDK configuration settings.'
+);
diff --git a/src/embedded/embeddedManager.test.ts b/src/embedded/embeddedManager.test.ts
index 904f1d2d..724a5890 100644
--- a/src/embedded/embeddedManager.test.ts
+++ b/src/embedded/embeddedManager.test.ts
@@ -1,4 +1,5 @@
 import { IterableEmbeddedManager } from './embeddedManager';
+import { setTypeOfAuthForTestingOnly } from '../authorization';
 
 // Mock the baseIterableRequest function
 jest.mock('../request', () => ({
@@ -11,6 +12,9 @@ jest.mock('..', () => ({
 }));
 
 describe('EmbeddedManager', () => {
+  beforeEach(() => {
+    setTypeOfAuthForTestingOnly('email');
+  });
   const appPackageName = 'my-website';
   describe('syncMessages', () => {
     it('should call syncMessages and callback', async () => {
@@ -28,7 +32,8 @@ describe('EmbeddedManager', () => {
       const embeddedManager = new IterableEmbeddedManager(appPackageName);
 
       async function mockTest() {
-        return new Promise(function (resolve, reject) {
+        return new Promise((resolve, reject) => {
+          // eslint-disable-next-line prefer-promise-reject-errors
           reject('Invalid API Key');
         });
       }
diff --git a/src/events/events.test.ts b/src/events/events.test.ts
index 7c3eac95..ea552160 100644
--- a/src/events/events.test.ts
+++ b/src/events/events.test.ts
@@ -13,8 +13,9 @@ import {
   trackInAppDelivery,
   trackInAppOpen
 } from './inapp/events';
-import { WEB_PLATFORM } from '../constants';
+import { INITIALIZE_ERROR, WEB_PLATFORM } from '../constants';
 import { createClientError } from '../utils/testUtils';
+import { setTypeOfAuthForTestingOnly } from '../authorization';
 
 const mockRequest = new MockAdapter(baseAxiosRequest);
 const localStorageMock = {
@@ -60,6 +61,11 @@ describe('Events Requests', () => {
     });
   });
 
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+    setTypeOfAuthForTestingOnly('userID');
+  });
+
   it('return the correct payload for track', async () => {
     const response = await track({ eventName: 'test' });
 
@@ -258,6 +264,54 @@ describe('Events Requests', () => {
       );
     }
   });
+  it('should fail trackInAppOpen if not authed', async () => {
+    try {
+      setTypeOfAuthForTestingOnly(null);
+      await trackInAppOpen({} as any);
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
+  it('should fail trackInAppClose if not authed', async () => {
+    try {
+      setTypeOfAuthForTestingOnly(null);
+      await trackInAppClose({} as any);
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
+  it('should fail trackInAppClick if not authed', async () => {
+    try {
+      setTypeOfAuthForTestingOnly(null);
+      await trackInAppClick({} as any);
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
+  it('should fail trackInAppConsume if not authed', async () => {
+    try {
+      setTypeOfAuthForTestingOnly(null);
+      await trackInAppConsume({} as any);
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
+  it('should fail trackInAppDelivery if not authed', async () => {
+    try {
+      setTypeOfAuthForTestingOnly(null);
+      await trackInAppDelivery({} as any);
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
+  it('should fail trackInAppOpen if not authed', async () => {
+    try {
+      setTypeOfAuthForTestingOnly(null);
+      await trackInAppOpen({} as any);
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
 
   it('return the correct payload for embedded message received', async () => {
     const response = await trackEmbeddedReceived('abc123', 'packageName');
@@ -477,4 +531,31 @@ describe('Events Requests', () => {
     expect(JSON.parse(trackSessionResponse.config.data).email).toBeUndefined();
     expect(JSON.parse(trackSessionResponse.config.data).userId).toBeUndefined();
   });
+
+  it('should fail if no auth type set for embedded received', async () => {
+    setTypeOfAuthForTestingOnly(null);
+    try {
+      await trackEmbeddedReceived('abc123', 'packageName');
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
+
+  it('should fail if no auth type set for embedded click', async () => {
+    setTypeOfAuthForTestingOnly(null);
+    try {
+      await trackEmbeddedClick({} as any);
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
+
+  it('should fail if no auth type set for embedded session', async () => {
+    setTypeOfAuthForTestingOnly(null);
+    try {
+      await trackEmbeddedSession({} as any);
+    } catch (e) {
+      expect(e).toBe(INITIALIZE_ERROR);
+    }
+  });
 });
diff --git a/src/events/events.ts b/src/events/events.ts
index 34f65075..6bae9314 100644
--- a/src/events/events.ts
+++ b/src/events/events.ts
@@ -1,15 +1,21 @@
 /* eslint-disable no-param-reassign */
-import { ENDPOINTS } from '../constants';
+import { ENDPOINTS, AUA_WARNING } from '../constants';
 import { baseIterableRequest } from '../request';
 import { InAppTrackRequestParams } from './inapp/types';
 import { IterableResponse } from '../types';
 import { trackSchema } from './events.schema';
+import { AnonymousUserEventManager } from '../anonymousUserTracking/anonymousUserEventManager';
+import { canTrackAnonUser } from '../utils/commonFunctions';
 
 export const track = (payload: InAppTrackRequestParams) => {
   /* a customer could potentially send these up if they're not using TypeScript */
   delete (payload as any).userId;
   delete (payload as any).email;
-
+  if (canTrackAnonUser()) {
+    const anonymousUserEventManager = new AnonymousUserEventManager();
+    anonymousUserEventManager.trackAnonEvent(payload);
+    return Promise.reject(AUA_WARNING);
+  }
   return baseIterableRequest<IterableResponse>({
     method: 'POST',
     url: ENDPOINTS.event_track.route,
diff --git a/src/inapp/inapp.ts b/src/inapp/inapp.ts
index 4265ae34..692ecae3 100644
--- a/src/inapp/inapp.ts
+++ b/src/inapp/inapp.ts
@@ -17,7 +17,7 @@ import {
   trackInAppClose,
   trackInAppConsume,
   trackInAppOpen
-} from '../events';
+} from '../events/inapp/events';
 import { IterablePromise } from '../types';
 import { requestMessages } from './request';
 import {
diff --git a/src/inapp/tests/inapp.test.ts b/src/inapp/tests/inapp.test.ts
index 5c40c7bc..86793a72 100644
--- a/src/inapp/tests/inapp.test.ts
+++ b/src/inapp/tests/inapp.test.ts
@@ -3,7 +3,7 @@
  */
 import MockAdapter from 'axios-mock-adapter';
 import { messages } from '../../__data__/inAppMessages';
-import { initialize } from '../../authorization';
+import { initialize, setTypeOfAuthForTestingOnly } from '../../authorization';
 import { GETMESSAGES_PATH, SDK_VERSION, WEB_PLATFORM } from '../../constants';
 import { baseAxiosRequest } from '../../request';
 import { createClientError } from '../../utils/testUtils';
@@ -20,6 +20,7 @@ describe('getInAppMessages', () => {
   beforeEach(() => {
     jest.clearAllMocks();
     jest.resetAllMocks();
+    setTypeOfAuthForTestingOnly('email');
     mockRequest.resetHistory();
 
     mockRequest.onGet(GETMESSAGES_PATH).reply(200, {
diff --git a/src/inapp/tests/utils.test.ts b/src/inapp/tests/utils.test.ts
index c80633e9..00778d42 100644
--- a/src/inapp/tests/utils.test.ts
+++ b/src/inapp/tests/utils.test.ts
@@ -19,6 +19,7 @@ import {
   sortInAppMessages,
   trackMessagesDelivered
 } from '../utils';
+import { setTypeOfAuthForTestingOnly } from '../../authorization';
 
 jest.mock('../../utils/srSpeak', () => ({
   srSpeak: jest.fn()
@@ -33,6 +34,9 @@ const mockMarkup = `
 `;
 
 describe('Utils', () => {
+  beforeEach(() => {
+    setTypeOfAuthForTestingOnly('email');
+  });
   describe('filterHiddenInAppMessages', () => {
     it('should filter out read messages', () => {
       expect(filterHiddenInAppMessages()).toEqual([]);
@@ -869,6 +873,7 @@ describe('Utils', () => {
 
       expect(el.getAttribute('aria-label')).toBe('hello');
       expect(el.getAttribute('role')).toBe('button');
+      // eslint-disable-next-line no-script-url
       expect(el.getAttribute('href')).toBe('javascript:undefined');
     });
 
diff --git a/src/index.ts b/src/index.ts
index e5169ad6..e6deee64 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -8,7 +8,7 @@ export * from './embedded';
 export * from './components/card';
 export * from './components/banner';
 export * from './components/notification';
-export { config } from './utils/config';
+export { config, IdentityResolution } from './utils/config';
 export { IterableConfig } from './utils/IterableConfig';
 
 export interface TextParentStyles {
diff --git a/src/request.ts b/src/request.ts
index 8badc433..6efa8cb8 100644
--- a/src/request.ts
+++ b/src/request.ts
@@ -1,9 +1,18 @@
 import Axios, { AxiosRequestConfig } from 'axios';
 import qs from 'qs';
 import { AnySchema, ValidationError } from 'yup';
-import { BASE_URL, STATIC_HEADERS, EU_ITERABLE_API } from './constants';
+import {
+  BASE_URL,
+  STATIC_HEADERS,
+  EU_ITERABLE_API,
+  GET_CRITERIA_PATH,
+  INITIALIZE_ERROR,
+  ENDPOINT_TRACK_ANON_SESSION
+} from './constants';
 import { IterablePromise, IterableResponse } from './types';
 import { config } from './utils/config';
+import { getTypeOfAuth } from './utils/typeOfAuth';
+import AuthorizationToken from './utils/authorizationToken';
 
 interface ExtendedRequestConfig extends AxiosRequestConfig {
   validation?: {
@@ -20,6 +29,11 @@ interface ClientError extends IterableResponse {
   }[];
 }
 
+const ENDPOINTS_NOT_REQUIRING_TYPE_OF_AUTH = [
+  GET_CRITERIA_PATH,
+  ENDPOINT_TRACK_ANON_SESSION
+];
+
 export const baseAxiosRequest = Axios.create({
   baseURL: BASE_URL
 });
@@ -28,6 +42,15 @@ export const baseIterableRequest = <T = any>(
   payload: ExtendedRequestConfig
 ): IterablePromise<T> => {
   try {
+    const endpoint = payload?.url ?? '';
+
+    // for most Iterable API endpoints, we require a user to be initialized in the SDK.
+    if (
+      !ENDPOINTS_NOT_REQUIRING_TYPE_OF_AUTH.includes(endpoint) &&
+      getTypeOfAuth() === null
+    ) {
+      return Promise.reject(INITIALIZE_ERROR);
+    }
     if (payload.validation?.data && payload.data) {
       payload.validation.data.validateSync(payload.data, { abortEarly: false });
     }
@@ -41,12 +64,17 @@ export const baseIterableRequest = <T = any>(
       ? EU_ITERABLE_API
       : config.getConfig('baseURL');
 
+    const authorizationToken = new AuthorizationToken();
+    const JWT = authorizationToken.getToken();
+    const Authorization = JWT ? `Bearer ${JWT}` : undefined;
+
     return baseAxiosRequest({
       ...payload,
       baseURL,
       headers: {
         ...payload.headers,
-        ...STATIC_HEADERS
+        ...STATIC_HEADERS,
+        Authorization
       },
       paramsSerializer: (params) =>
         qs.stringify(params, { arrayFormat: 'repeat' })
diff --git a/src/users/types.ts b/src/users/types.ts
index d0f7c5c8..5cafc406 100644
--- a/src/users/types.ts
+++ b/src/users/types.ts
@@ -12,10 +12,14 @@ export interface GetUserResponse {
 
 export interface UpdateUserParams {
   dataFields?: Record<string, any>;
-  preferUserId?: boolean;
   mergeNestedObjects?: boolean;
 }
 
+export interface UpdateAnonymousUserParams extends UpdateUserParams {
+  createNewFields?: boolean;
+  userId?: string;
+}
+
 export interface UpdateSubscriptionParams {
   emailListIds: number[];
   unsubscribedChannelIds: number[];
diff --git a/src/users/users.schema.ts b/src/users/users.schema.ts
index 91e0443f..4557a18a 100644
--- a/src/users/users.schema.ts
+++ b/src/users/users.schema.ts
@@ -1,6 +1,7 @@
-import { array, boolean, number, object } from 'yup';
+import { array, boolean, number, object, string } from 'yup';
 
 export const updateUserSchema = object().shape({
+  userId: string(),
   dataFields: object(),
   preferUserId: boolean(),
   mergeNestedObjects: boolean()
diff --git a/src/users/users.test.ts b/src/users/users.test.ts
index 3ec297c9..940b2b3b 100644
--- a/src/users/users.test.ts
+++ b/src/users/users.test.ts
@@ -2,11 +2,22 @@ import MockAdapter from 'axios-mock-adapter';
 import { baseAxiosRequest } from '../request';
 import { updateSubscriptions, updateUser, updateUserEmail } from './users';
 import { createClientError } from '../utils/testUtils';
+import { setTypeOfAuthForTestingOnly } from '../authorization';
 // import { SDK_VERSION, WEB_PLATFORM } from '../constants';
 
 const mockRequest = new MockAdapter(baseAxiosRequest);
 
+const localStorageMock = {
+  getItem: jest.fn(),
+  setItem: jest.fn(),
+  removeItem: jest.fn()
+};
+
 describe('Users Requests', () => {
+  beforeEach(() => {
+    (global as any).localStorage = localStorageMock;
+    setTypeOfAuthForTestingOnly('email');
+  });
   it('should set params and return the correct payload for updateUser', async () => {
     mockRequest.onPost('/users/update').reply(200, {
       msg: 'hello'
@@ -16,11 +27,13 @@ describe('Users Requests', () => {
       dataFields: {}
     });
 
-    expect(JSON.parse(response.config.data).dataFields).toEqual({});
-    expect(JSON.parse(response.config.data).preferUserId).toBe(true);
+    expect(JSON.parse(response && response.config.data).dataFields).toEqual({});
+    expect(JSON.parse(response && response.config.data).preferUserId).toBe(
+      true
+    );
     // expect(response.config.headers['SDK-Version']).toBe(SDK_VERSION);
     // expect(response.config.headers['SDK-Platform']).toBe(WEB_PLATFORM);
-    expect(response.data.msg).toBe('hello');
+    expect(response && response.data.msg).toBe('hello');
   });
 
   it('should reject updateUser on bad params', async () => {
diff --git a/src/users/users.ts b/src/users/users.ts
index 279a56a9..e8f4cc34 100644
--- a/src/users/users.ts
+++ b/src/users/users.ts
@@ -1,10 +1,12 @@
 // eslint-disable @typescript-eslint/no-explicit-any
 import { object, string } from 'yup';
-import { ENDPOINTS } from '../constants';
 import { IterableResponse } from '../types';
 import { baseIterableRequest } from '../request';
 import { UpdateSubscriptionParams, UpdateUserParams } from './types';
 import { updateSubscriptionsSchema, updateUserSchema } from './users.schema';
+import { AnonymousUserEventManager } from '../anonymousUserTracking/anonymousUserEventManager';
+import { canTrackAnonUser } from '../utils/commonFunctions';
+import { AUA_WARNING, ENDPOINTS } from '../constants';
 
 export const updateUserEmail = (newEmail: string) =>
   baseIterableRequest<IterableResponse>({
@@ -26,6 +28,11 @@ export const updateUser = (payloadParam: UpdateUserParams = {}) => {
   delete (payload as any).userId;
   delete (payload as any).email;
 
+  if (canTrackAnonUser()) {
+    const anonymousUserEventManager = new AnonymousUserEventManager();
+    anonymousUserEventManager.trackAnonUpdateUser(payload);
+    return Promise.reject(AUA_WARNING);
+  }
   return baseIterableRequest<IterableResponse>({
     method: 'POST',
     url: ENDPOINTS.users_update.route,
diff --git a/src/utils/authorizationToken.ts b/src/utils/authorizationToken.ts
new file mode 100644
index 00000000..e8fec965
--- /dev/null
+++ b/src/utils/authorizationToken.ts
@@ -0,0 +1,21 @@
+import { SHARED_PREF_USER_TOKEN } from '../constants';
+
+class AuthorizationToken {
+  public token: string | null = null;
+
+  setToken(token: string) {
+    this.token = token;
+    localStorage.setItem(SHARED_PREF_USER_TOKEN, token);
+  }
+
+  getToken(): string | null {
+    return this.token || localStorage.getItem(SHARED_PREF_USER_TOKEN);
+  }
+
+  clearToken() {
+    this.token = '';
+    localStorage.removeItem(SHARED_PREF_USER_TOKEN);
+  }
+}
+
+export default AuthorizationToken;
diff --git a/src/utils/commonFunctions.ts b/src/utils/commonFunctions.ts
new file mode 100644
index 00000000..46471516
--- /dev/null
+++ b/src/utils/commonFunctions.ts
@@ -0,0 +1,5 @@
+import config from './config';
+import { getTypeOfAuth } from './typeOfAuth';
+
+export const canTrackAnonUser = (): boolean =>
+  config.getConfig('enableAnonActivation') && getTypeOfAuth() === null;
diff --git a/src/utils/config.ts b/src/utils/config.ts
index 491314e9..42c74969 100644
--- a/src/utils/config.ts
+++ b/src/utils/config.ts
@@ -1,18 +1,33 @@
-import { BASE_URL } from '../constants';
+import { BASE_URL, DEFAULT_EVENT_THRESHOLD_LIMIT } from '../constants';
+
+export type IdentityResolution = {
+  replayOnVisitorToKnown?: boolean;
+  mergeOnAnonymousToKnown?: boolean;
+};
 
 export type Options = {
   logLevel: 'none' | 'verbose';
   baseURL: string;
+  enableAnonActivation: boolean;
   isEuIterableService: boolean;
   dangerouslyAllowJsPopups: boolean;
+  eventThresholdLimit?: number;
+  onAnonUserCreated?: (userId: string) => void;
+  identityResolution?: IdentityResolution;
 };
 
 const _config = () => {
   let options: Options = {
     logLevel: 'none',
     baseURL: BASE_URL,
+    enableAnonActivation: false,
     isEuIterableService: false,
-    dangerouslyAllowJsPopups: false
+    dangerouslyAllowJsPopups: false,
+    eventThresholdLimit: DEFAULT_EVENT_THRESHOLD_LIMIT,
+    identityResolution: {
+      replayOnVisitorToKnown: true,
+      mergeOnAnonymousToKnown: true
+    }
   };
 
   const getConfig = <K extends keyof Options>(option: K) => options[option];
@@ -22,7 +37,11 @@ const _config = () => {
     setConfig: (newOptions: Partial<Options>) => {
       options = {
         ...options,
-        ...newOptions
+        ...newOptions,
+        identityResolution: {
+          ...options.identityResolution,
+          ...newOptions.identityResolution
+        }
       };
     }
   };
diff --git a/src/utils/typeOfAuth.ts b/src/utils/typeOfAuth.ts
new file mode 100644
index 00000000..38092020
--- /dev/null
+++ b/src/utils/typeOfAuth.ts
@@ -0,0 +1,24 @@
+/* eslint-disable import/no-mutable-exports */
+
+/*
+    AKA did the user auth with their email (setEmail) or user ID (setUserID)
+
+    we're going to use this variable for one circumstance - when calling _updateUserEmail_.
+    Essentially, when we call the Iterable API to update a user's email address and we get a
+    successful 200 request, we're going to request a new JWT token, since it might need to
+    be re-signed with the new email address; however, if the customer code never authorized the
+    user with an email and instead a user ID, we'll just continue to sign the JWT with the user ID.
+
+    This is mainly just a quality-of-life feature, so that the customer's JWT generation code
+    doesn't _need_ to support email-signed JWTs if they don't want and purely want to issue the
+    tokens by user ID.
+  */
+/* this will be the literal user ID or email they choose to auth with */
+
+export type TypeOfAuth = null | 'email' | 'userID';
+let typeOfAuth: TypeOfAuth = null;
+export const setTypeOfAuth = (value: TypeOfAuth) => {
+  typeOfAuth = value;
+};
+
+export const getTypeOfAuth = () => typeOfAuth;
diff --git a/src/utils/types.ts b/src/utils/types.ts
new file mode 100644
index 00000000..656aadeb
--- /dev/null
+++ b/src/utils/types.ts
@@ -0,0 +1,21 @@
+import { UpdateAnonymousUserParams } from '..';
+
+interface AnonSessionContext {
+  totalAnonSessionCount?: number;
+  lastAnonSession?: number;
+  firstAnonSession?: number;
+  webPushOptIn?: string;
+  lastPage?: string;
+  matchedCriteriaId: number;
+}
+
+export interface TrackAnonSessionParams {
+  user: UpdateAnonymousUserParams;
+  createdAt: number;
+  deviceInfo: {
+    deviceId: string;
+    appPackageName: string; // customer-defined name
+    platform: string;
+  };
+  anonSessionContext: AnonSessionContext;
+}
diff --git a/yarn.lock b/yarn.lock
index 31e79372..28d76dfc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1902,7 +1902,7 @@
   resolved "https://registry.yarnpkg.com/@types/throttle-debounce/-/throttle-debounce-2.1.0.tgz#1c3df624bfc4b62f992d3012b84c56d41eab3776"
   integrity sha512-5eQEtSCoESnh2FsiLTxE121IiE60hnMqcb435fShf4bpLRjEu1Eoekht23y6zXS9Ts3l+Szu3TARnTsA0GkOkQ==
 
-"@types/uuid@^9.0.2":
+"@types/uuid@^9.0.8":
   version "9.0.8"
   resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba"
   integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==