Skip to content

Commit

Permalink
Edgee 406 react sdk export edgee sdk methods (#7)
Browse files Browse the repository at this point in the history
* init

* Add DataCollection Method Support with Queue and Types

* update types

* Add Consent handling to exports

* update

* Update Readme
  • Loading branch information
Jer1605 authored Feb 6, 2025
1 parent af4255a commit 8338e1f
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 4 deletions.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
`react-edgee` is a React component that injects the Edgee SDK script into a React application.

It also sets up listeners to track page navigations via `history.pushState` and `history.replaceState`
to automatically call the `edgee.page` method, ensuring page views are tracked during SPA navigations.
to automatically call the `edgee.page` method, ensuring page views are tracked during SPA navigations, and provides a **React Hook** (`useEdgeeDataCollection`) to simplify event tracking (`track`, `user`, `page`, `consent`).


[![NPM](https://img.shields.io/badge/NPM-%23CB3837.svg?style=for-the-badge&logo=npm&logoColor=white)](https://www.npmjs.com/package/react-edgee)
[![NPM Downloads](https://img.shields.io/npm/dm/react-edgee?&style=flat-square)](https://www.npmjs.com/package/react-edgee)
Expand Down Expand Up @@ -110,6 +111,25 @@ const App = () => {
export default App;
```

### 🔥 Using the React Hook (`useEdgeeDataCollection`)

The `useEdgeeDataCollection` hook simplifies event tracking by providing direct access to the Edgee [SDK methods](https://www.edgee.cloud/docs/services/data-collection/overview).

```js
import { useEdgeeDataCollection } from 'react-edgee';

const MyComponent = () => {
const { track, user, page, consent } = useEdgeeDataCollection();

return (
<>
<button onClick={() => track({ name: 'button_click' })}>Click Me</button>
<button onClick={() => user({ user_id: '12345', edgee_id: 'edgee-abc' })}>Identify User</button>
<button onClick={() => page({ name: 'HomePage', url: 'https://example.com' })}>Track Page</button>
<button onClick={() => consent('granted')}>Accept Consent</button>
</>
);
};
```

To learn more about the Edgee SDK, visit the [Edgee SDK documentation](https://www.edgee.cloud/docs/getting-started/sdk).
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-edgee",
"version": "1.1.1",
"version": "1.2.0",
"description": "React component to use the Edgee SDK",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
12 changes: 10 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import * as PropTypes from 'prop-types';
import * as React from 'react';
import { useEdgeeDataCollection } from './lib/data-collection/data-collection.hook';
import { Consent } from './lib/data-collection/data-collection.types';

/**
* Interface representing the Edgee analytics object.
* Provides methods for tracking page, track, and user events.
*/
interface Edgee {
export interface Edgee {
/**
* Tracks a page view event.
* @param arg - The event name or an object containing event properties.
Expand All @@ -28,6 +30,12 @@ interface Edgee {
* @param components - Optional object specifying components for the event.
*/
user: (arg?: string | object, components?: object) => void;

/**
* Consent management system that allows you to control data collection and anonymization based on user consent status.
* @param {Consent} status - Consent state. Could be pending, denied or granted.
*/
consent: (status: Consent) => void;
}

// Extends the global Window interface to include the Edgee analytics object.
Expand Down Expand Up @@ -156,7 +164,7 @@ const EdgeeDataLayer = ({ data }: EdgeeDataLayerProps): JSX.Element => {
);
};

export { EdgeeSdk, EdgeeDataLayer };
export { EdgeeSdk, EdgeeDataLayer, useEdgeeDataCollection };

EdgeeSdk.propTypes = {
src: PropTypes.string,
Expand Down
56 changes: 56 additions & 0 deletions src/lib/data-collection/data-collection.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useCallback } from 'react';
import { track, page, user, consent } from './data-collection';
import { Consent, Page, Track, User } from './data-collection.types';

/**
* Custom hook `useEdgeeDataCollection`
*
* Provides access to Edgee's tracking methods: `track`, `page`, `user`, and `consent`.
* - Returns memoized functions for tracking events and user identification.
*
* @returns {{
* track: (eventData: Track) => void;
* page: (pageData: Page) => void;
* user: (userData: User) => void;
* consent: (consent: Consent) => void;
* }} Object containing the tracking functions.
*/
export const useEdgeeDataCollection = () => {
/**
* Tracks a page event.
*
* @param {Page} pageData - The page details to be sent to Edgee.
*/
const pageEvent = useCallback((pageData: Page) => {
page(pageData);
}, []);

/**
* Tracks a custom event.
*
* @param {Track} trackData - The event details to be sent to Edgee.
*/
const trackEvent = useCallback((trackData: Track) => {
track(trackData);
}, []);

/**
* Identifies a user and associates events with them.
*
* @param {User} userData - The user data to be sent to Edgee.
*/
const userEvent = useCallback((userData: User) => {
user(userData);
}, []);

/**
* Set the consent for a user.
*
* @param {Consent} status - The status of the consent for the user.
*/
const setConsent = useCallback((status: Consent) => {
consent(status);
}, []);

return { track: trackEvent, page: pageEvent, user: userEvent, consent: setConsent };
};
69 changes: 69 additions & 0 deletions src/lib/data-collection/data-collection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Edgee } from '../../index';
import {
Page,
User,
Track,
Consent,
EdgeeMethod,
EdgeeConsentMethod,
QueuedEvent,
QueuedConsentEvent,
} from './data-collection.types';

const eventQueue: (QueuedEvent<Page | User | Track | Consent> | QueuedConsentEvent)[] = [];

/**
* Flushes the event queue and sends all stored events to `window.edgee` if available.
*/
const flushQueue = () => {
if (typeof window !== 'undefined' && window.edgee) {
while (eventQueue.length > 0) {
const event = eventQueue.shift();
if (!event) return;
try {
event.method === 'consent'
? (window.edgee as Edgee)[event.method](event.args[0])
: (window.edgee as Edgee)[event.method](...event.args);
} catch (e) {
return e;
}
}
}
};

/**
* Creates a method that queues events if `window.edgee` is not available yet.
* @param {keyof Edgee} method - The name of the tracking method (`track`, `user`, `page`).
* @returns {EdgeeMethod<T>} A function that queues or sends the event.
*/
const createMethod =
<T extends Page | User | Track>(method: Exclude<keyof Edgee, 'consent'>): EdgeeMethod<T> =>
(arg: T, components?: Record<string, boolean>) => {
if (typeof window !== 'undefined' && window.edgee) {
flushQueue();
window.edgee[method](arg, components);
} else {
eventQueue.push({ method, args: [arg, components] });
}
};

/**
* Creates a consent method that queues events if `window.edgee` is not available yet.
* @returns {EdgeeConsentMethod} A function that queues or sends the consent event.
*/
const createConsentMethod = (): EdgeeConsentMethod => (arg: Consent) => {
if (typeof window !== 'undefined' && window.edgee) {
flushQueue();
window.edgee.consent(arg);
} else {
eventQueue.push({ method: 'consent', args: [arg] });
}
};

export const track: EdgeeMethod<Track> = createMethod<Track>('track');
export const user: EdgeeMethod<User> = createMethod<User>('user');
export const page: EdgeeMethod<Page> = createMethod<Page>('page');
export const consent: EdgeeConsentMethod = createConsentMethod();

const EdgeeSDK = { track, user, page, consent };
export default EdgeeSDK;
40 changes: 40 additions & 0 deletions src/lib/data-collection/data-collection.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Edgee } from '../../index';

export interface Page {
name?: string;
category?: string;
keywords?: string[];
title?: string;
url?: string;
path?: string;
search?: string;
referrer?: string;
properties?: Record<string, unknown>;
}

export interface User {
user_id?: string;
anonymous_id?: string;
edgee_id: string;
properties?: Record<string, unknown>;
}

export interface Track {
name?: string;
properties?: Record<string, unknown>;
}

export type Consent = 'granted' | 'denied' | 'pending';

export type EdgeeMethod<T> = (arg: T, components?: Record<string, boolean>) => void;
export type EdgeeConsentMethod = (arg: Consent) => void;

export type QueuedEvent<T> = {
method: Exclude<keyof Edgee, 'consent'>;
args: [T, Record<string, boolean>?];
};

export type QueuedConsentEvent = {
method: 'consent';
args: [Consent];
};

0 comments on commit 8338e1f

Please sign in to comment.