Skip to content

Commit

Permalink
feat: Add cohesion directory with helper functions
Browse files Browse the repository at this point in the history
  • Loading branch information
julianajlk committed Oct 18, 2024
1 parent c01b35f commit 29daa15
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/cohesion/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const EventMap = {
ProductClicked: 'redventures.ecommerce.v1.ProductClicked',
ProductLoaded: 'redventures.ecommerce.v1.ProductLoaded',
ProductViewed: 'redventures.ecommerce.v1.ProductViewed',
ElementClicked: 'redventures.usertracking.v3.ElementClicked',
ElementViewed: 'redventures.usertracking.v3.ElementViewed',
FieldSelected: 'redventures.usertracking.v3.FieldSelected',
FormSubmitted: 'redventures.usertracking.v3.FormSubmitted',
FormViewed: 'redventures.usertracking.v3.FormViewed',
};

export default EventMap;
33 changes: 33 additions & 0 deletions src/cohesion/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import EventMap from './constants';

/**
* Submit ('beam') an event via Tagular to Make
* @param eventName Schema Name of the Event
* @param eventData The data required by the schema
*/
export const tagularEvent = (eventName, eventData) => {
// if tagular is available, try sending given event with event data
if (typeof window !== 'undefined' && window.tagular) {
try {
window.tagular('beam', eventName, {
'@type': EventMap[eventName],
...eventData,
});
} catch (error) {
// eslint-disable-next-line no-console
console.warn(`Tagular event ${eventName} not sent.`, error);
}
} else {
// eslint-disable-next-line no-console
console.warn('Tagular not available on page.');
}
};

export function pageTrackingObject(pageType) {
return {
title: window.document.title,
url: window.location.href,
pageType,
referrer: window.document.referrer,
};
}
71 changes: 71 additions & 0 deletions src/cohesion/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import {
useCallback,
useEffect,
useRef,
useState,
} from 'react';

export const IS_FULLY_SHOWN_THRESHOLD_OR_MARGIN = 1.0;
export const IS_SINGLE_PX_SHOWN_THRESHOLD_OR_MARGIN = 0.0;
export const DOCUMENT_ROOT_NODE = null;

const defaultOptions = {
threshold: IS_FULLY_SHOWN_THRESHOLD_OR_MARGIN,
root: DOCUMENT_ROOT_NODE,
};

/**
Hook to track if an element is intersecting with a root (null represents <html>).
@param callback The callback to be invoked when an item intersects.
@param options The options for IntersectionObserver.
*/
export const useIntersectionObserver = (callback, options = defaultOptions) => {
const ref = useRef(null);

useEffect(() => {
if (!ref.current) { return; }
const refCurrent = ref.current;

const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
callback(entry);
}
});
}, options);

if (ref.current) {
observer.observe(refCurrent);
}

// eslint-disable-next-line consistent-return
return () => {
if (refCurrent) {
observer.unobserve(refCurrent);
}
};
}, [callback, options]);

return ref;
};

/**
Hook to track an element's intersection but only trigger callback once per element.
@param callback The callback to be invoked once the item is shown.
@param options Intersection observer options.
*/
export const useSingleCallIntersectionObserver = (callback, options = defaultOptions) => {
const [hasBeenShown, setHasBeenShown] = useState(false);

const handleVisibilityChange = useCallback((entry) => {
if (!hasBeenShown) {
callback(entry);
setHasBeenShown(true);
}
}, [callback, hasBeenShown]);

return useIntersectionObserver(handleVisibilityChange, options);
};

export default useSingleCallIntersectionObserver;
export const useIsShowing = useIntersectionObserver;

0 comments on commit 29daa15

Please sign in to comment.