diff --git a/README.md b/README.md
index 28b85507..91bef444 100644
--- a/README.md
+++ b/README.md
@@ -40,14 +40,21 @@ yarn add @every-analytics/react-analytics-provider
You can check examples [here](https://github.com/EveryAnalytics/react-analytics-provider/tree/main/demo)
```tsx
-import {AnalyticsProvider} from '@every-analytics/react-analytics-provider';
+import {Analytics, AnalyticsProvider} from '@every-analytics/react-analytics-provider';
+
+const analytics: Analytics = {
+ initialize: () => console.log('onInitialize'),
+ trackPageView: params => console.log('onTrackPageView', params),
+ trackEvent: (name, params) => console.log('onTrackEvent', name, params),
+ trackClick: (name, params) => console.log('onTrackClick', name, params),
+ set: (...args) => console.log('onSet', args),
+ setUserId: userId => console.log("onSetUserId", userId),
+ setUserProperty: params => console.log("onSetUserProperty", params),
+}
console.log('initialized')}
- onPageView={(params) => console.log('pageview', params)}
- onEvent={(name, params) => console.log('event', name, params)}
- onClick={(name, params) => console.log('click', name, params)}
- onSetUserId={(userId) => console.log('setUserId', userId)}
+ analytics={analytics}
>
diff --git a/demo/with-cra/src/components/NavBar.tsx b/demo/with-cra/src/components/NavBar.tsx
index f3f3437a..d9bf14c3 100644
--- a/demo/with-cra/src/components/NavBar.tsx
+++ b/demo/with-cra/src/components/NavBar.tsx
@@ -1,17 +1,17 @@
// import { logEvent } from "@every-analytics/react-analytics-provider";
import React from 'react';
import navigate from 'router/navigate';
-import {useAnalyticsContext} from '@every-analytics/react-analytics-provider';
+import {useAnalytics} from '@every-analytics/react-analytics-provider';
const NavBar = () => {
- const analytics = useAnalyticsContext();
+ const analytics = useAnalytics();
return (
{
- analytics.onEvent('Click logo');
+ analytics.trackEvent('Click logo');
}}
>
Fruit Store
@@ -19,7 +19,7 @@ const NavBar = () => {
{
- analytics.onEvent('Click products', {color: 'red'});
+ analytics.trackEvent('Click products', {color: 'red'});
}}
>
Red
@@ -27,7 +27,7 @@ const NavBar = () => {
{
- analytics.onEvent('Click products', {color: 'yellow'});
+ analytics.trackEvent('Click products', {color: 'yellow'});
}}
>
Yellow
@@ -35,7 +35,7 @@ const NavBar = () => {
{
- analytics.onClick('Click login', {color: 'yellow'});
+ analytics.trackClick('Click login', {color: 'yellow'});
}}
>
Login
@@ -43,7 +43,7 @@ const NavBar = () => {
{
- analytics.onSet({currency: 'KRW'});
+ analytics.set({currency: 'KRW'});
}}
>
Currency
diff --git a/demo/with-cra/src/index.tsx b/demo/with-cra/src/index.tsx
index 90e25f98..9a9f9bed 100644
--- a/demo/with-cra/src/index.tsx
+++ b/demo/with-cra/src/index.tsx
@@ -2,7 +2,12 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
-import {AnalyticsProvider, googleAnalyticsHelper, amplitudeHelper} from '@every-analytics/react-analytics-provider';
+import {
+ Analytics,
+ AnalyticsProvider,
+ googleAnalyticsHelper,
+ amplitudeHelper,
+} from '@every-analytics/react-analytics-provider';
import {fruitLogger} from './utils/fruitLogger';
import {Toaster} from 'react-hot-toast';
import {toaster} from './utils/toaster';
@@ -10,44 +15,46 @@ import {toaster} from './utils/toaster';
amplitudeHelper.initialize(process.env.REACT_APP_AMPLITUDE_API_KEY);
const persistentValues = {userNo: 123};
+const analytics: Analytics = {
+ initialize: () => {
+ googleAnalyticsHelper.initialize(process.env.REACT_APP_GA_TRACKING_ID, persistentValues);
+ },
+ trackPageView: params => {
+ // NOTE: Google Analytics(GA4)는 기본적으로 페이지뷰가 적용됩니다 - 따로 추가 필요X
+ const path = window.location.pathname + window.location.search;
+ fruitLogger.pageView(path, params);
+ toaster.pageView(path, params);
+ amplitudeHelper.logEvent('pageView', {path});
+ },
+ trackEvent: (name, params) => {
+ googleAnalyticsHelper.event(name, params);
+ fruitLogger.event(name, params);
+ toaster.event(name, params);
+ },
+ trackClick: (name, params) => {
+ googleAnalyticsHelper.click(name, params);
+ fruitLogger.click(name, params);
+ toaster.click(name, params);
+ },
+ set: (...args: Parameters) => {
+ googleAnalyticsHelper.set(...args);
+ fruitLogger.set(...args);
+ toaster.set(...args);
+ },
+ setUserId: userId => {
+ // TODO: UserId 설정하는 코드 추가
+ console.log(userId);
+ },
+ setUserProperty: params => {
+ googleAnalyticsHelper.setUserProperty(params);
+ fruitLogger.setUserProperty(params);
+ toaster.setUserProperty(params);
+ },
+};
+
ReactDOM.render(
- {
- googleAnalyticsHelper.initialize(process.env.REACT_APP_GA_TRACKING_ID, persistentValues);
- }}
- onPageView={params => {
- // NOTE: Google Analytics(GA4)는 기본적으로 페이지뷰가 적용됩니다 - 따로 추가 필요X
- const path = window.location.pathname + window.location.search;
- fruitLogger.pageView(path, params);
- toaster.pageView(path, params);
- amplitudeHelper.logEvent('pageView', {path});
- }}
- onEvent={(name, params) => {
- googleAnalyticsHelper.event(name, params);
- fruitLogger.event(name, params);
- toaster.event(name, params);
- }}
- onClick={(name, params) => {
- googleAnalyticsHelper.click(name, params);
- fruitLogger.click(name, params);
- toaster.click(name, params);
- }}
- onSet={(...args: Parameters) => {
- googleAnalyticsHelper.set(...args);
- fruitLogger.set(...args);
- toaster.set(...args);
- }}
- onSetUserId={userId => {
- // TODO: UserId 설정하는 코드 추가
- console.log(userId);
- }}
- onSetUserProperty={params => {
- googleAnalyticsHelper.setUserProperty(params);
- fruitLogger.setUserProperty(params);
- toaster.setUserProperty(params);
- }}
- >
+
{
- const analytics = useAnalyticsContext();
+ const analytics = useAnalytics();
useEffect(() => {
- analytics.onPageView();
+ analytics.trackPageView();
}, [analytics]);
return Set Currency KRW
;
diff --git a/demo/with-cra/src/pages/ProductsPage/index.tsx b/demo/with-cra/src/pages/ProductsPage/index.tsx
index b2c4a426..fb7b6b36 100644
--- a/demo/with-cra/src/pages/ProductsPage/index.tsx
+++ b/demo/with-cra/src/pages/ProductsPage/index.tsx
@@ -1,14 +1,14 @@
import {useEffect} from 'react';
import {getQueryParams} from 'utils/location';
-import {useAnalyticsContext} from '@every-analytics/react-analytics-provider';
+import {useAnalytics} from '@every-analytics/react-analytics-provider';
const ProductsPage = () => {
const {color} = getQueryParams<{color: string}>();
const products = getProductsByColor(color);
- const analytics = useAnalyticsContext();
+ const analytics = useAnalytics();
useEffect(() => {
- analytics.onPageView();
+ analytics.trackPageView();
}, [analytics]);
return (
diff --git a/demo/with-cra/src/pages/UserPropertyPage/index.tsx b/demo/with-cra/src/pages/UserPropertyPage/index.tsx
index b391071e..e7294ab8 100644
--- a/demo/with-cra/src/pages/UserPropertyPage/index.tsx
+++ b/demo/with-cra/src/pages/UserPropertyPage/index.tsx
@@ -1,16 +1,16 @@
import {useEffect, useState} from 'react';
-import {useAnalyticsContext} from '@every-analytics/react-analytics-provider';
+import {useAnalytics} from '@every-analytics/react-analytics-provider';
const SetUserPropertyPage = () => {
- const analytics = useAnalyticsContext();
+ const analytics = useAnalytics();
useEffect(() => {
- analytics.onPageView();
+ analytics.trackPageView();
}, [analytics]);
const [favoriteFood, setFavoriteFood] = useState('한식');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
- analytics.onSetUserProperty({favoriteFood});
+ analytics.setUserProperty({favoriteFood});
};
return (
diff --git a/demo/with-nextjs/src/pages/_app.tsx b/demo/with-nextjs/src/pages/_app.tsx
index 85fd63d5..9bae1797 100644
--- a/demo/with-nextjs/src/pages/_app.tsx
+++ b/demo/with-nextjs/src/pages/_app.tsx
@@ -1,28 +1,38 @@
-import {AnalyticsProvider} from '@every-analytics/react-analytics-provider';
+import {Analytics, AnalyticsProvider} from '@every-analytics/react-analytics-provider';
import {AppProps} from 'next/app';
import {Layout} from '../layout/Layout';
function DemoApp({Component, pageProps}: AppProps) {
+ const analytics: Analytics = {
+ initialize: () => {
+ console.log('onInitialize');
+ },
+ trackPageView: params => {
+ // NOTE: Google Analytics(GA4)는 기본적으로 페이지뷰가 적용됩니다 - 따로 추가 필요X
+ // TODO: 이준희 => ga, amplitude event tracking 코드 추가
+ console.log('onTrackPageView', params);
+ },
+ trackEvent: (name, params) => {
+ // TODO: 이준희 => ga, amplitude event tracking 코드 추가
+ console.log('onTrackEvent', name, params);
+ },
+ trackClick: (name, params) => {
+ // TODO: 이준희 => ga, amplitude event tracking 코드 추가
+ console.log('onTrackClick', name, params);
+ },
+ set: (...args) => {
+ console.log('onSet', args);
+ },
+ setUserId: userId => {
+ console.log('onSetUserId', userId);
+ },
+ setUserProperty: params => {
+ console.log('onSetUserProperty', params);
+ },
+ };
+
return (
- {
- // TODO: 이준희 => ga, amplitude event tracking 코드 추가
- console.log('onInitialize');
- }}
- onPageView={params => {
- // NOTE: Google Analytics(GA4)는 기본적으로 페이지뷰가 적용됩니다 - 따로 추가 필요X
- // TODO: 이준희 => ga, amplitude event tracking 코드 추가
- console.log('onPageView', params);
- }}
- onEvent={(name, params) => {
- // TODO: 이준희 => ga, amplitude event tracking 코드 추가
- console.log('onEvent', name, params);
- }}
- onClick={(name, params) => {
- // TODO: 이준희 => ga, amplitude event tracking 코드 추가
- console.log('onClick', name, params);
- }}
- >
+
diff --git a/src/components/AnalyticsClick/index.tsx b/src/components/AnalyticsClick/index.tsx
index bf1dc019..04bbe5ea 100644
--- a/src/components/AnalyticsClick/index.tsx
+++ b/src/components/AnalyticsClick/index.tsx
@@ -1,5 +1,5 @@
import React, {useCallback} from 'react';
-import {useAnalyticsContext} from '../../contexts';
+import {useAnalytics} from '../../contexts';
import {UnknownRecord} from '../../types/common';
export interface AnalyticsClickProps {
@@ -9,13 +9,13 @@ export interface AnalyticsClickProps {
}
export const AnalyticsClick = ({children, name, params}: AnalyticsClickProps) => {
- const {onClick} = useAnalyticsContext();
+ const {trackClick} = useAnalytics();
const child = React.Children.only(children) as React.ReactElement;
const handleChildClick = useCallback(() => {
- onClick(name, {action_type: 'click', ...params});
- }, [name, params, onClick]);
+ trackClick(name, {action_type: 'click', ...params});
+ }, [name, params, trackClick]);
return React.cloneElement(child, {
onClick: handleChildClick,
diff --git a/src/components/AnalyticsPageView/index.tsx b/src/components/AnalyticsPageView/index.tsx
index ea4964b6..fa8e3e51 100644
--- a/src/components/AnalyticsPageView/index.tsx
+++ b/src/components/AnalyticsPageView/index.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import {useAnalyticsContext} from '../../contexts/useAnalyticsContext';
+import {useAnalytics} from '../../contexts/useAnalytics';
import {UnknownRecord} from '../../types/common';
export interface AnalyticsPageViewProps {
@@ -8,10 +8,10 @@ export interface AnalyticsPageViewProps {
}
export const AnalyticsPageView = ({children, params}: AnalyticsPageViewProps) => {
- const analytics = useAnalyticsContext();
+ const analytics = useAnalytics();
React.useEffect(() => {
- analytics.onPageView(params);
+ analytics.trackPageView(params);
}, [analytics, params]);
return <>{children}>;
diff --git a/src/components/AnalyticsProvider/index.tsx b/src/components/AnalyticsProvider/index.tsx
index 7f35f78d..f91e4fb5 100644
--- a/src/components/AnalyticsProvider/index.tsx
+++ b/src/components/AnalyticsProvider/index.tsx
@@ -1,48 +1,20 @@
import * as React from 'react';
import AnalyticsProviderContext from '../../contexts/AnalyticsProviderContext';
-import {UnknownRecord} from '../../types/common';
+import {Analytics} from '../../core';
interface Props {
- onInitialize(): void;
- onPageView?(params?: UnknownRecord): void;
- onEvent?(name: string, params?: UnknownRecord): void;
- onClick?(name: string, params?: UnknownRecord): void;
- onSet?(...args: [string, UnknownRecord] | [UnknownRecord]): void;
- onSetUserId?(userId: string | null): void;
- onSetUserProperty?(params: UnknownRecord): void;
+ analytics: Analytics;
children: React.ReactNode;
}
-export function AnalyticsProvider({
- onInitialize,
- onPageView = () => null,
- onEvent = () => null,
- onClick = () => null,
- onSet = () => null,
- onSetUserId = () => null,
- onSetUserProperty = () => null,
- children,
-}: Props) {
+export function AnalyticsProvider({analytics, children}: Props) {
React.useEffect(() => {
- onInitialize();
- }, [onInitialize]);
+ analytics.initialize();
+ }, [analytics]);
return React.useMemo(
- () => (
-
- {children}
-
- ),
- [children, onClick, onEvent, onPageView, onSet, onSetUserId, onSetUserProperty],
+ () => {children},
+ [children, analytics],
);
}
diff --git a/src/contexts/AnalyticsProviderContext.ts b/src/contexts/AnalyticsProviderContext.ts
index 624f99c3..ded768be 100644
--- a/src/contexts/AnalyticsProviderContext.ts
+++ b/src/contexts/AnalyticsProviderContext.ts
@@ -1,24 +1,16 @@
import {createContext} from 'react';
-import {UnknownRecord} from '../types/common';
+import {Analytics} from '../core';
-export interface AnalyticsProviderContext {
- onPageView(params?: UnknownRecord): void;
- onEvent(name: string, params?: UnknownRecord): void;
- onClick(name: string, params?: UnknownRecord): void;
- onSet(...args: [string, UnknownRecord] | [UnknownRecord]): void;
- onSetUserId(userId: string | null): void;
- onSetUserProperty(params: UnknownRecord): void;
-}
-
-export const initialState: AnalyticsProviderContext = {
- onPageView: () => null,
- onEvent: () => null,
- onClick: () => null,
- onSet: () => null,
- onSetUserId: () => null,
- onSetUserProperty: () => null,
+const initialState: Analytics = {
+ initialize: () => null,
+ trackPageView: () => null,
+ trackEvent: () => null,
+ trackClick: () => null,
+ set: () => null,
+ setUserId: () => null,
+ setUserProperty: () => null,
};
-const AnalyticsProviderContext = createContext(initialState);
+const AnalyticsProviderContext = createContext(initialState);
export default AnalyticsProviderContext;
diff --git a/src/contexts/index.ts b/src/contexts/index.ts
index 1377eedf..955ac594 100644
--- a/src/contexts/index.ts
+++ b/src/contexts/index.ts
@@ -1 +1 @@
-export * from './useAnalyticsContext';
+export * from './useAnalytics';
diff --git a/src/contexts/useAnalyticsContext.ts b/src/contexts/useAnalytics.ts
similarity index 79%
rename from src/contexts/useAnalyticsContext.ts
rename to src/contexts/useAnalytics.ts
index 1c4f6eb0..8b298c99 100644
--- a/src/contexts/useAnalyticsContext.ts
+++ b/src/contexts/useAnalytics.ts
@@ -1,6 +1,6 @@
import * as React from 'react';
import AnalyticsProviderContext from './AnalyticsProviderContext';
-export function useAnalyticsContext() {
+export function useAnalytics() {
return React.useContext(AnalyticsProviderContext);
}
diff --git a/src/core/Analytics.ts b/src/core/Analytics.ts
new file mode 100644
index 00000000..5586017f
--- /dev/null
+++ b/src/core/Analytics.ts
@@ -0,0 +1,11 @@
+import {UnknownRecord} from '../types/common';
+
+export interface Analytics {
+ initialize(): void;
+ trackPageView(params?: UnknownRecord): void;
+ trackEvent(name: string, params?: UnknownRecord): void;
+ trackClick(name: string, params?: UnknownRecord): void;
+ set(...args: [string, UnknownRecord] | [UnknownRecord]): void;
+ setUserId(userId: string | null): void;
+ setUserProperty(params: UnknownRecord): void;
+}
diff --git a/src/core/index.ts b/src/core/index.ts
new file mode 100644
index 00000000..dca4ebe3
--- /dev/null
+++ b/src/core/index.ts
@@ -0,0 +1 @@
+export * from './Analytics';
diff --git a/src/hooks/useAnalyticsPageView.ts b/src/hooks/useAnalyticsPageView.ts
index ca37e3b3..6f7ad65a 100644
--- a/src/hooks/useAnalyticsPageView.ts
+++ b/src/hooks/useAnalyticsPageView.ts
@@ -1,16 +1,16 @@
import React from 'react';
-import {useAnalyticsContext} from '../contexts/useAnalyticsContext';
+import {useAnalytics} from '../contexts/useAnalytics';
import {UnknownRecord} from '../types/common';
export function useAnalyticsPageView(params: UnknownRecord): void;
export function useAnalyticsPageView(callback: () => UnknownRecord): void;
export function useAnalyticsPageView(callback: () => Promise): void;
export function useAnalyticsPageView(paramsOrCallback: UnknownRecord | (() => Promise | UnknownRecord)) {
- const analytics = useAnalyticsContext();
+ const analytics = useAnalytics();
const pageView = async () => {
const params = typeof paramsOrCallback === 'function' ? await paramsOrCallback() : paramsOrCallback;
- analytics.onPageView(params);
+ analytics.trackPageView(params);
};
React.useEffect(() => {
diff --git a/src/index.tsx b/src/index.tsx
index bdd15d0d..61216f16 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -2,3 +2,4 @@ export * from './components';
export * from './utils';
export * from './contexts';
export * from './hooks';
+export * from './core';
diff --git a/tests/hooks/useAnalyticsPageView.test.ts b/tests/hooks/useAnalyticsPageView.test.ts
index 057a63c2..d83f9556 100644
--- a/tests/hooks/useAnalyticsPageView.test.ts
+++ b/tests/hooks/useAnalyticsPageView.test.ts
@@ -1,7 +1,7 @@
import React from 'react';
import * as faker from 'faker';
-import * as contextModule from '../../src/contexts/useAnalyticsContext';
+import * as contextModule from '../../src/contexts/useAnalytics';
import {useAnalyticsPageView} from '../../src/hooks/useAnalyticsPageView';
describe('useAnalyticsPageView', () => {
@@ -10,13 +10,13 @@ describe('useAnalyticsPageView', () => {
const callback = () => params;
const asyncCallback = async () => params;
- const onPageView = jest.fn();
+ const trackPageView = jest.fn();
const useEffectSpy = jest.spyOn(React, 'useEffect').mockImplementationOnce(cb => cb());
- const useContextSpy = jest.spyOn(contextModule, 'useAnalyticsContext').mockImplementationOnce(
+ const useContextSpy = jest.spyOn(contextModule, 'useAnalytics').mockImplementationOnce(
() =>
({
- onPageView,
+ trackPageView,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -26,7 +26,7 @@ describe('useAnalyticsPageView', () => {
params,
callback,
asyncCallback,
- onPageView,
+ trackPageView,
useEffectSpy,
useContextSpy,
};
@@ -34,36 +34,36 @@ describe('useAnalyticsPageView', () => {
const waitForAsync = () => new Promise(resolve => setTimeout(resolve, 0));
- test('should call analytics.onPageView with params', async () => {
- const {params, onPageView, useContextSpy, useEffectSpy} = setUp();
+ test('should call analytics.trackPageView with params', async () => {
+ const {params, trackPageView, useContextSpy, useEffectSpy} = setUp();
useAnalyticsPageView(params);
await waitForAsync();
expect(useContextSpy).toHaveBeenCalled();
expect(useEffectSpy).toHaveBeenCalled();
- expect(onPageView).toHaveBeenCalledWith(params);
+ expect(trackPageView).toHaveBeenCalledWith(params);
});
- test('should call analytics.onPageView with callback', async () => {
- const {params, callback, onPageView, useContextSpy, useEffectSpy} = setUp();
+ test('should call analytics.trackPageView with callback', async () => {
+ const {params, callback, trackPageView, useContextSpy, useEffectSpy} = setUp();
useAnalyticsPageView(callback);
await waitForAsync();
expect(useContextSpy).toHaveBeenCalled();
expect(useEffectSpy).toHaveBeenCalled();
- expect(onPageView).toHaveBeenCalledWith(params);
+ expect(trackPageView).toHaveBeenCalledWith(params);
});
- test('should call analytics.onPageView with asyncCallback', async () => {
- const {params, asyncCallback, onPageView, useContextSpy, useEffectSpy} = setUp();
+ test('should call analytics.trackPageView with asyncCallback', async () => {
+ const {params, asyncCallback, trackPageView, useContextSpy, useEffectSpy} = setUp();
useAnalyticsPageView(asyncCallback);
await waitForAsync();
expect(useContextSpy).toHaveBeenCalled();
expect(useEffectSpy).toHaveBeenCalled();
- expect(onPageView).toHaveBeenCalledWith(params);
+ expect(trackPageView).toHaveBeenCalledWith(params);
});
});