diff --git a/.eslintrc.json b/.eslintrc.json index 2cfcc0ff..3238cdee 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -19,7 +19,8 @@ "prettier/prettier": ["error", {"endOfLine":"auto"}], "@typescript-eslint/explicit-module-boundary-types": "off", "react/react-in-jsx-scope": "off", - "import/no-unresolved": "off" + "import/no-unresolved": "off", + "jsx-a11y/no-onchange": "off" }, "settings": { "react": { diff --git a/demo/with-cra/src/App.tsx b/demo/with-cra/src/App.tsx index 1b71aa12..ac11d5b6 100644 --- a/demo/with-cra/src/App.tsx +++ b/demo/with-cra/src/App.tsx @@ -2,6 +2,8 @@ import NavBar from './components/NavBar'; import MainPage from './pages/MainPage'; import ProductsPage from './pages/ProductsPage'; import LoginPage from './pages/LoginPage'; +import CurrencyPage from './pages/CurrencyPage'; +import UserPropertyPage from './pages/UserPropertyPage'; import Route from './router/Route'; function App() { @@ -17,6 +19,12 @@ function App() { + + + + + + ); } diff --git a/demo/with-cra/src/components/NavBar.tsx b/demo/with-cra/src/components/NavBar.tsx index 99e67db4..f3f3437a 100644 --- a/demo/with-cra/src/components/NavBar.tsx +++ b/demo/with-cra/src/components/NavBar.tsx @@ -40,6 +40,15 @@ const NavBar = () => { > Login + { + analytics.onSet({currency: 'KRW'}); + }} + > + Currency + + UserProperty ); }; diff --git a/demo/with-cra/src/index.tsx b/demo/with-cra/src/index.tsx index 7948f96e..197f7fbc 100644 --- a/demo/with-cra/src/index.tsx +++ b/demo/with-cra/src/index.tsx @@ -34,6 +34,16 @@ ReactDOM.render( fruitLogger.click(name, params); toaster.click(name, params); }} + onSet={(...args: Parameters) => { + googleAnalytics.set(...args); + fruitLogger.set(...args); + toaster.set(...args); + }} + onSetUserProperty={params => { + googleAnalytics.setUserProperty(params); + fruitLogger.setUserProperty(params); + toaster.setUserProperty(params); + }} > diff --git a/demo/with-cra/src/pages/CurrencyPage/index.tsx b/demo/with-cra/src/pages/CurrencyPage/index.tsx new file mode 100644 index 00000000..d18e17f5 --- /dev/null +++ b/demo/with-cra/src/pages/CurrencyPage/index.tsx @@ -0,0 +1,13 @@ +import {useEffect} from 'react'; +import {useAnalyticsContext} from '@every-analytics/react-analytics-provider'; + +const CurrencyPage = () => { + const analytics = useAnalyticsContext(); + useEffect(() => { + analytics.onPageView(); + }, [analytics]); + + return

Set Currency KRW

; +}; + +export default CurrencyPage; diff --git a/demo/with-cra/src/pages/UserPropertyPage/index.tsx b/demo/with-cra/src/pages/UserPropertyPage/index.tsx new file mode 100644 index 00000000..b391071e --- /dev/null +++ b/demo/with-cra/src/pages/UserPropertyPage/index.tsx @@ -0,0 +1,33 @@ +import {useEffect, useState} from 'react'; +import {useAnalyticsContext} from '@every-analytics/react-analytics-provider'; + +const SetUserPropertyPage = () => { + const analytics = useAnalyticsContext(); + useEffect(() => { + analytics.onPageView(); + }, [analytics]); + + const [favoriteFood, setFavoriteFood] = useState('한식'); + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + analytics.onSetUserProperty({favoriteFood}); + }; + + return ( +
+
+ + +
+ ); +}; + +export default SetUserPropertyPage; diff --git a/demo/with-cra/src/utils/fruitLogger/index.ts b/demo/with-cra/src/utils/fruitLogger/index.ts index 7a6abb80..81ce926f 100644 --- a/demo/with-cra/src/utils/fruitLogger/index.ts +++ b/demo/with-cra/src/utils/fruitLogger/index.ts @@ -1,15 +1,31 @@ -const pageView = (path: string, params?: {[key: string]: any}) => { +type UnknownRecord = Record; + +const pageView = (path: string, params?: UnknownRecord) => { console.info('🥝Fruit Logger - PageView', params); }; -const event = (name: string, params?: {[key: string]: any}) => { +const event = (name: string, params?: UnknownRecord) => { console.info('🥝Fruit Logger - Event', name, params); }; -const click = (name: string, params?: {[key: string]: any}) => { +const click = (name: string, params?: UnknownRecord) => { console.info('🥝Fruit Logger - Click', name, params); }; +const set = (...args: [string, UnknownRecord] | [UnknownRecord]) => { + const params = args.pop(); + const name = args.pop(); + if (name === undefined) { + console.info('🥝Fruit Logger - Set', params); + } else { + console.info('🥝Fruit Logger - Set', name, params); + } +}; +const setUserProperty = (params: UnknownRecord) => { + set('user_properties', params); +}; export const fruitLogger = { pageView, event, click, + set, + setUserProperty, }; diff --git a/demo/with-cra/src/utils/toaster/index.tsx b/demo/with-cra/src/utils/toaster/index.tsx index 1dde3f95..ed191e44 100644 --- a/demo/with-cra/src/utils/toaster/index.tsx +++ b/demo/with-cra/src/utils/toaster/index.tsx @@ -35,8 +35,26 @@ export const pageView = (path: string, params?: unknown) => { ); }; +export const set = (...args: [string, unknown] | [unknown]) => { + const params = args.pop(); + const name = args.pop(); + showToast( + <> +
GA: Set
+ {name &&
name: {name}
} +
params: {JSON.stringify(params)}
+ , + ); +}; + +export const setUserProperty = (params: unknown) => { + set('user_properties', params); +}; + export const toaster = { event, click, pageView, + set, + setUserProperty, }; diff --git a/src/components/AnalyticsProvider/index.tsx b/src/components/AnalyticsProvider/index.tsx index 5e285b98..b99c2c08 100644 --- a/src/components/AnalyticsProvider/index.tsx +++ b/src/components/AnalyticsProvider/index.tsx @@ -8,6 +8,8 @@ interface Props { onPageView?(params?: UnknownRecord): void; onEvent?(name: string, params?: UnknownRecord): void; onClick?(name: string, params?: UnknownRecord): void; + onSet?(...args: [string, UnknownRecord] | [UnknownRecord]): void; + onSetUserProperty?(params: UnknownRecord): void; children: React.ReactNode; } @@ -16,6 +18,8 @@ export function AnalyticsProvider({ onPageView = () => null, onEvent = () => null, onClick = () => null, + onSet = () => null, + onSetUserProperty = () => null, children, }: Props) { React.useEffect(() => { @@ -29,11 +33,13 @@ export function AnalyticsProvider({ onPageView, onEvent, onClick, + onSet, + onSetUserProperty, }} > {children} ), - [children, onClick, onEvent, onPageView], + [children, onClick, onEvent, onPageView, onSet, onSetUserProperty], ); } diff --git a/src/contexts/AnalyticsProviderContext.ts b/src/contexts/AnalyticsProviderContext.ts index fa31423a..7ced3960 100644 --- a/src/contexts/AnalyticsProviderContext.ts +++ b/src/contexts/AnalyticsProviderContext.ts @@ -5,12 +5,16 @@ 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; + onSetUserProperty(params: UnknownRecord): void; } export const initialState: AnalyticsProviderContext = { onPageView: () => null, onEvent: () => null, onClick: () => null, + onSet: () => null, + onSetUserProperty: () => null, }; const AnalyticsProviderContext = createContext(initialState); diff --git a/src/utils/googleAnalytics/index.ts b/src/utils/googleAnalytics/index.ts index e515b24d..4e2e17fd 100644 --- a/src/utils/googleAnalytics/index.ts +++ b/src/utils/googleAnalytics/index.ts @@ -2,10 +2,12 @@ import {event} from './event'; import {click} from './click'; import {initialize} from './initialize'; import {set} from './set'; +import {setUserProperty} from './setUserProperty'; export const googleAnalytics = { initialize, event, click, set, + setUserProperty, }; diff --git a/src/utils/googleAnalytics/set.ts b/src/utils/googleAnalytics/set.ts index 2e4525ce..77d95e3b 100644 --- a/src/utils/googleAnalytics/set.ts +++ b/src/utils/googleAnalytics/set.ts @@ -5,7 +5,14 @@ import {gtag} from './initialize'; /** Allows you to set values that persist across all the subsequent gtag() calls on the page. * {@link https://developers.google.com/gtagjs/reference/api#set API Reference} * @param params key-value pairs that are to persist across gtag() calls. */ -export function set(params: UnknownRecord) { - console.info(`✅GA: set`, params); - gtag('set', params); +export function set(...args: [string, UnknownRecord] | [UnknownRecord]) { + const params = args.pop(); + const name = args.pop(); + if (name === undefined) { + console.info(`✅GA: set`, params); + gtag('set', params); + } else { + console.info(`✅GA: set ${name}`, params); + gtag('set', name, params); + } } diff --git a/src/utils/googleAnalytics/setUserProperty.ts b/src/utils/googleAnalytics/setUserProperty.ts new file mode 100644 index 00000000..3f9bfb4a --- /dev/null +++ b/src/utils/googleAnalytics/setUserProperty.ts @@ -0,0 +1,6 @@ +import {UnknownRecord} from '../../types/common'; +import {set} from './set'; + +export function setUserProperty(params: UnknownRecord) { + return set('user_properties', params); +}