Skip to content

Commit 0162e71

Browse files
alledyDayoung Kangmilooy
authored
feat: Refactor set function and implement setUserProperty function with demo (#113)
* feat: Refactor set function to allow overloading * Update src/utils/googleAnalytics/set.ts Co-authored-by: Yurim Jalynne Jin <[email protected]> * refactor: change set function to use rest parameter with tuple unions * feat: Add demo with set function * feat: Implement SetUserProperty function * chore: Make jsx-a11y/no-onchange rule off in eslint config * feat: Add demo for setUserProperty Co-authored-by: Dayoung Kang <[email protected]> Co-authored-by: Yurim Jalynne Jin <[email protected]>
1 parent 1369187 commit 0162e71

File tree

13 files changed

+141
-8
lines changed

13 files changed

+141
-8
lines changed

.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"prettier/prettier": ["error", {"endOfLine":"auto"}],
2020
"@typescript-eslint/explicit-module-boundary-types": "off",
2121
"react/react-in-jsx-scope": "off",
22-
"import/no-unresolved": "off"
22+
"import/no-unresolved": "off",
23+
"jsx-a11y/no-onchange": "off"
2324
},
2425
"settings": {
2526
"react": {

demo/with-cra/src/App.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import NavBar from './components/NavBar';
22
import MainPage from './pages/MainPage';
33
import ProductsPage from './pages/ProductsPage';
44
import LoginPage from './pages/LoginPage';
5+
import CurrencyPage from './pages/CurrencyPage';
6+
import UserPropertyPage from './pages/UserPropertyPage';
57
import Route from './router/Route';
68

79
function App() {
@@ -17,6 +19,12 @@ function App() {
1719
<Route path="/login">
1820
<LoginPage />
1921
</Route>
22+
<Route path="/set-currency">
23+
<CurrencyPage />
24+
</Route>
25+
<Route path="/set-user-property">
26+
<UserPropertyPage />
27+
</Route>
2028
</div>
2129
);
2230
}

demo/with-cra/src/components/NavBar.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ const NavBar = () => {
4040
>
4141
Login
4242
</NavItem>
43+
<NavItem
44+
href="/set-currency"
45+
onClick={() => {
46+
analytics.onSet({currency: 'KRW'});
47+
}}
48+
>
49+
Currency
50+
</NavItem>
51+
<NavItem href="/set-user-property">UserProperty</NavItem>
4352
</header>
4453
);
4554
};

demo/with-cra/src/index.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ ReactDOM.render(
3434
fruitLogger.click(name, params);
3535
toaster.click(name, params);
3636
}}
37+
onSet={(...args: Parameters<typeof googleAnalytics.set>) => {
38+
googleAnalytics.set(...args);
39+
fruitLogger.set(...args);
40+
toaster.set(...args);
41+
}}
42+
onSetUserProperty={params => {
43+
googleAnalytics.setUserProperty(params);
44+
fruitLogger.setUserProperty(params);
45+
toaster.setUserProperty(params);
46+
}}
3747
>
3848
<App />
3949
</AnalyticsProvider>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {useEffect} from 'react';
2+
import {useAnalyticsContext} from '@every-analytics/react-analytics-provider';
3+
4+
const CurrencyPage = () => {
5+
const analytics = useAnalyticsContext();
6+
useEffect(() => {
7+
analytics.onPageView();
8+
}, [analytics]);
9+
10+
return <h1>Set Currency KRW</h1>;
11+
};
12+
13+
export default CurrencyPage;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {useEffect, useState} from 'react';
2+
import {useAnalyticsContext} from '@every-analytics/react-analytics-provider';
3+
4+
const SetUserPropertyPage = () => {
5+
const analytics = useAnalyticsContext();
6+
useEffect(() => {
7+
analytics.onPageView();
8+
}, [analytics]);
9+
10+
const [favoriteFood, setFavoriteFood] = useState('한식');
11+
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
12+
e.preventDefault();
13+
analytics.onSetUserProperty({favoriteFood});
14+
};
15+
16+
return (
17+
<form onSubmit={handleSubmit}>
18+
<br />
19+
<label>
20+
Pick your favorite flavor:
21+
<select value={favoriteFood} onChange={e => setFavoriteFood(e.target.value)}>
22+
<option value="한식">한식</option>
23+
<option value="중식">중식</option>
24+
<option value="일식">일식</option>
25+
<option value="양식">양식</option>
26+
</select>
27+
</label>
28+
<button type="submit">Submit</button>
29+
</form>
30+
);
31+
};
32+
33+
export default SetUserPropertyPage;
Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
1-
const pageView = (path: string, params?: {[key: string]: any}) => {
1+
type UnknownRecord = Record<string, unknown>;
2+
3+
const pageView = (path: string, params?: UnknownRecord) => {
24
console.info('🥝Fruit Logger - PageView', params);
35
};
4-
const event = (name: string, params?: {[key: string]: any}) => {
6+
const event = (name: string, params?: UnknownRecord) => {
57
console.info('🥝Fruit Logger - Event', name, params);
68
};
7-
const click = (name: string, params?: {[key: string]: any}) => {
9+
const click = (name: string, params?: UnknownRecord) => {
810
console.info('🥝Fruit Logger - Click', name, params);
911
};
12+
const set = (...args: [string, UnknownRecord] | [UnknownRecord]) => {
13+
const params = args.pop();
14+
const name = args.pop();
15+
if (name === undefined) {
16+
console.info('🥝Fruit Logger - Set', params);
17+
} else {
18+
console.info('🥝Fruit Logger - Set', name, params);
19+
}
20+
};
21+
const setUserProperty = (params: UnknownRecord) => {
22+
set('user_properties', params);
23+
};
1024

1125
export const fruitLogger = {
1226
pageView,
1327
event,
1428
click,
29+
set,
30+
setUserProperty,
1531
};

demo/with-cra/src/utils/toaster/index.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,26 @@ export const pageView = (path: string, params?: unknown) => {
3535
);
3636
};
3737

38+
export const set = (...args: [string, unknown] | [unknown]) => {
39+
const params = args.pop();
40+
const name = args.pop();
41+
showToast(
42+
<>
43+
<div>GA: Set</div>
44+
{name && <div>name: {name}</div>}
45+
<div>params: {JSON.stringify(params)}</div>
46+
</>,
47+
);
48+
};
49+
50+
export const setUserProperty = (params: unknown) => {
51+
set('user_properties', params);
52+
};
53+
3854
export const toaster = {
3955
event,
4056
click,
4157
pageView,
58+
set,
59+
setUserProperty,
4260
};

src/components/AnalyticsProvider/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ interface Props {
88
onPageView?(params?: UnknownRecord): void;
99
onEvent?(name: string, params?: UnknownRecord): void;
1010
onClick?(name: string, params?: UnknownRecord): void;
11+
onSet?(...args: [string, UnknownRecord] | [UnknownRecord]): void;
12+
onSetUserProperty?(params: UnknownRecord): void;
1113
children: React.ReactNode;
1214
}
1315

@@ -16,6 +18,8 @@ export function AnalyticsProvider({
1618
onPageView = () => null,
1719
onEvent = () => null,
1820
onClick = () => null,
21+
onSet = () => null,
22+
onSetUserProperty = () => null,
1923
children,
2024
}: Props) {
2125
React.useEffect(() => {
@@ -29,11 +33,13 @@ export function AnalyticsProvider({
2933
onPageView,
3034
onEvent,
3135
onClick,
36+
onSet,
37+
onSetUserProperty,
3238
}}
3339
>
3440
{children}
3541
</AnalyticsProviderContext.Provider>
3642
),
37-
[children, onClick, onEvent, onPageView],
43+
[children, onClick, onEvent, onPageView, onSet, onSetUserProperty],
3844
);
3945
}

src/contexts/AnalyticsProviderContext.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@ export interface AnalyticsProviderContext {
55
onPageView(params?: UnknownRecord): void;
66
onEvent(name: string, params?: UnknownRecord): void;
77
onClick(name: string, params?: UnknownRecord): void;
8+
onSet(...args: [string, UnknownRecord] | [UnknownRecord]): void;
9+
onSetUserProperty(params: UnknownRecord): void;
810
}
911

1012
export const initialState: AnalyticsProviderContext = {
1113
onPageView: () => null,
1214
onEvent: () => null,
1315
onClick: () => null,
16+
onSet: () => null,
17+
onSetUserProperty: () => null,
1418
};
1519

1620
const AnalyticsProviderContext = createContext<AnalyticsProviderContext>(initialState);

src/utils/googleAnalytics/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import {event} from './event';
22
import {click} from './click';
33
import {initialize} from './initialize';
44
import {set} from './set';
5+
import {setUserProperty} from './setUserProperty';
56

67
export const googleAnalytics = {
78
initialize,
89
event,
910
click,
1011
set,
12+
setUserProperty,
1113
};

src/utils/googleAnalytics/set.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ import {gtag} from './initialize';
55
/** Allows you to set values that persist across all the subsequent gtag() calls on the page.
66
* {@link https://developers.google.com/gtagjs/reference/api#set API Reference}
77
* @param params key-value pairs that are to persist across gtag() calls. */
8-
export function set(params: UnknownRecord) {
9-
console.info(`✅GA: set`, params);
10-
gtag('set', params);
8+
export function set(...args: [string, UnknownRecord] | [UnknownRecord]) {
9+
const params = args.pop();
10+
const name = args.pop();
11+
if (name === undefined) {
12+
console.info(`✅GA: set`, params);
13+
gtag('set', params);
14+
} else {
15+
console.info(`✅GA: set ${name}`, params);
16+
gtag('set', name, params);
17+
}
1118
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import {UnknownRecord} from '../../types/common';
2+
import {set} from './set';
3+
4+
export function setUserProperty(params: UnknownRecord) {
5+
return set('user_properties', params);
6+
}

0 commit comments

Comments
 (0)