Skip to content

Commit

Permalink
fix(analytics.ts): ๐Ÿ›analytics setup
Browse files Browse the repository at this point in the history
  • Loading branch information
AlgoRoots committed Mar 8, 2024
1 parent 20e944e commit c06d0c9
Show file tree
Hide file tree
Showing 12 changed files with 1,960 additions and 1,900 deletions.
6 changes: 3 additions & 3 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ NEXT_PUBLIC_KAKAO_CLIENT_ID=''
NEXT_PUBLIC_NAVER_CLIENT_ID=''
NEXT_PUBLIC_AUTH_TOKEN_KEY=toktokhan

NEXT_PUBLIC_FACEBOOK_PIXEL_KEY = ''
NEXT_PUBLIC_GA_KEY = ''
NEXT_PUBLIC_KAKAO_PIXEL_KEY = ''
NEXT_PUBLIC_FACEBOOK_PIXEL_KEY=
NEXT_PUBLIC_GA_KEY=
NEXT_PUBLIC_KAKAO_PIXEL_KEY=
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ module.exports = {
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-namespace': 'off',
'@next/next/no-img-element': 'off',
},
settings: {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
"@testing-library/react": "^14.0.0",
"@tosspayments/payment-sdk": "^1.1.1",
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
"@types/facebook-pixel": "^0.0.25",
"@types/facebook-pixel": "^0.0.30",
"@types/gtag.js": "^0.0.12",
"@types/kakao-pixel": "^0.11.0",
"@types/lodash-es": "^4.17.8",
Expand Down
2 changes: 0 additions & 2 deletions src/containers/Home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from 'react';

import { Box, Text } from '@chakra-ui/react';

function Home() {
Expand Down
6 changes: 4 additions & 2 deletions src/pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ class MyDocument extends Document {
<Html>
<Head>
<script dangerouslySetInnerHTML={this.redirectIEtoEdge()} />
{/* Global site tag (gtag.js) - Google Analytics */}
{/* {GASetter()} */}
{/* ๋ถ„์„๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ฃผ์„ ํ•ด์ œ ํ›„ ์‚ฌ์šฉํ•ด์ฃผ์„ธ์š”. src/utils/analytics/analytics.ts ์„ค์ • ํ•„์š” */}
{/* {GASetter()}
{KakaoSetter()}
{FacebookSetter()} */}
</Head>
<body>
<ColorModeScript initialColorMode={config.initialColorMode} />
Expand Down
66 changes: 23 additions & 43 deletions src/utils/analytics/analytics.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,31 @@
import { ENV } from '@/configs/env';

import { ENV } from '../../configs/env';
import { FacebookAnalytics } from './facebook';
import { GoogleAnalytics } from './google';
import { KakaoAnalytics } from './kakao';

const googleAnalytics = ENV.GA_KEY
? new GoogleAnalytics(ENV.GA_KEY)
: console.error('should set GA key');

const facebookAnalytics = ENV.FACEBOOK_PIXEL_KEY
? new FacebookAnalytics(ENV.FACEBOOK_PIXEL_KEY)
: console.error('should set facebook key');

const kakaoAnalytics = ENV.KAKAO_PIXEL_KEY
? new KakaoAnalytics(ENV.KAKAO_PIXEL_KEY)
: console.error('should set Kakao pixel key');

export const completeRegistrationAnalytics = (social: string) => {
googleAnalytics?.completeRegistration(social);
facebookAnalytics?.completeRegistration(social);
kakaoAnalytics?.completeRegistration(social);
};

export const startProjectAnalytics = (params: { id: string; step: string }) => {
googleAnalytics?.startProject(params);
facebookAnalytics?.startProject(params);
kakaoAnalytics?.startProject(params);
};

export const completeProjectAnalytics = (id: string) => {
googleAnalytics?.completeProject(id);
facebookAnalytics?.completeProject(id);
kakaoAnalytics?.completeProject(id);
};

export const consultingApplyAnalytics = () => {
googleAnalytics?.consultingApply();
facebookAnalytics?.consultingApply();
kakaoAnalytics?.consultingApply();
};

export const requestApplyAnalytics = () => {
googleAnalytics?.requestApply();
facebookAnalytics?.requestApply();
kakaoAnalytics?.requestApply();
import { Analytics } from './types';

/**
* ํ•„์š”ํ•˜์ง€ ์•Š์€ ๋ถ„์„ ๋„๊ตฌ๋Š” ์ด ์ฝ”๋“œ์—์„œ ์ œ๊ฑฐํ•ด์ฃผ์„ธ์š”.
* ๋‹จ์ผ ๋ถ„์„ ๋„๊ตฌ๋งŒ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ํ•ด๋‹น ๋„๊ตฌ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
useEffect(() => {
facebookAnalytics?.pageView({ content_name: 'page2', content_ids: [2] });
}, [])
*/

export const googleAnalytics = new GoogleAnalytics(ENV.GA_KEY);
export const facebookAnalytics = new FacebookAnalytics(ENV.FACEBOOK_PIXEL_KEY);
export const kakaoAnalytics = new KakaoAnalytics(ENV.KAKAO_PIXEL_KEY);

/** Google Analytics, Facebook Pixel, Kakao Pixel์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์•„๋ž˜์˜ ํ•จ์ˆ˜๋ฅผ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. */
export const completeRegistrationAnalytics = (
params: Analytics.CompleteRegistration,
) => {
googleAnalytics?.completeRegistration(params.Ga);
facebookAnalytics?.completeRegistration(params.Fbq);
kakaoAnalytics?.completeRegistration(params.Kakao);
};

/** ๊ฐ ๋ถ„์„ ๋„๊ตฌ์˜ ์„ค์ • ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜๋“ค์ž…๋‹ˆ๋‹ค. */
export const GASetter = () => googleAnalytics?.GASetter();
export const FacebookSetter = () => facebookAnalytics?.FacebookSetter();
export const KakaoSetter = () => kakaoAnalytics?.KakaoSetter();
108 changes: 70 additions & 38 deletions src/utils/analytics/facebook.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,93 @@
import React from 'react';

import { Analytics } from './types';
import { analyticsValidCheckHandler } from './utils/valid-check-with-proxy';

/**
* @brief Meta pixel(Facebook) event๊ฐ€ ์ •์˜ ๋œ class์ž…๋‹ˆ๋‹ค.
* @description Meta ํ”ฝ์…€์˜ fbq('track') ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ ํ‘œ์ค€ ์ด๋ฒคํŠธ๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
* ๋˜ํ•œ ํ‘œ์ค€ ์ด๋ฒคํŠธ๋Š” ํŠน์ • ๊ฐœ์ฒด ์†์„ฑ์ด ํฌํ•จ๋œ ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐœ์ฒด๋ฅผ ์ง€์›ํ•˜๋ฏ€๋กœ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์ƒ์„ธํ•œ ์ •๋ณด๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
* @see Docs https://developers.facebook.com/docs/meta-pixel/reference#object-properties
* @see Docs https://developers.facebook.com/docs/marketing-api/conversions-api/guides/gtm-server-side?locale=ko_KR
*/

export class FacebookAnalytics {
public facebookAnalytics: facebook.Pixel.Event = typeof window !== "undefined" ? window.fbq : () => {};
private fbq: facebook.Pixel.Event = () => {};

constructor(private key: string) {
/**
* FacebookAnalytics ํด๋ž˜์Šค์˜ ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
* @param key Facebook ํ”ฝ์…€ ํ‚ค์ž…๋‹ˆ๋‹ค.
*/
constructor(private key?: string) {
if (!key) {
console.warn('Facebook ํ‚ค ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.');
return;
}
this.key = key;
this.fbq = new Proxy(
{
fbq: typeof window !== 'undefined' ? window.fbq : () => {},
},
analyticsValidCheckHandler,
).fbq;
}

completeRegistration = (social: string) => {
this.facebookAnalytics('track', 'CompleteRegistration', {
content_name: social,
});
/**๋“ฑ๋ก ์–‘์‹์„ ์ž‘์„ฑ ์™„๋ฃŒํ•œ ๊ฒฝ์šฐ.
* ์–ด๋–ค ์‚ฌ๋žŒ์ด ์ž‘์„ฑํ•œ ๊ตฌ๋… ๋˜๋Š” ๋“ฑ๋ก ์–‘์‹์„ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค.
* @param {string} content_name - ํŽ˜์ด์ง€/์ œํ’ˆ์˜ ์ด๋ฆ„
* @param {string} currency - value์— ์ง€์ •๋œ ํ†ตํ™”
* @param {number} value -๋น„์ฆˆ๋‹ˆ์Šค์—์„œ ์ด ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰ํ•œ ์‚ฌ์šฉ์ž์˜ ๊ฐ€์น˜
*/
completeRegistration = (params: Analytics.CompleteRegistration['Fbq']) => {
this.fbq('track', 'CompleteRegistration', params);
};

startProject = (params: { id: string; step: string }) => {
window.fbq('track', 'ViewContent', {
contents_id: params.id,
content_name: 'StartProject',
});
/**
* ํŽ˜์ด์ง€ ๋ทฐ : ๋ฉ”์ธ+ ์ƒ์„ธ+ ๊ธฐํƒ€ ๋ชจ๋“  ํŽ˜์ด์ง€
* @param {number[]} content_ids - ์ด๋ฒคํŠธ์™€ ์—ฐ๊ฒฐ๋œ ์ œํ’ˆ ID(์˜ˆ: SKU(['ABC123', 'XYZ789'] ๋“ฑ))
* @param {string} content_name - ํŽ˜์ด์ง€/์ œํ’ˆ์˜ ์ด๋ฆ„
*/
pageView = (params: Analytics.PageView['Fbq']) => {
this.fbq('track', 'ViewContent', params);
};

completeProject = (id: string) => {
window.fbq('track', 'ViewContent', {
content_name: 'CompleteProject',
content_ids: id,
});
/**
* ์ฝ˜ํ…์ธ  ์กฐํšŒ : ๋ณดํ†ต ์ƒ์„ธํŽ˜์ด์ง€๋ฅผ ์˜๋ฏธ
* ViewContent๋Š” ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์›นํŽ˜์ด์ง€ URL์— ๋ฐฉ๋ฌธํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ฃผ์ง€๋งŒ ๊ทธ ๋ฐฉ๋ฌธ์ž๊ฐ€ ํ•ด๋‹น ํŽ˜์ด์ง€์—์„œ ๋ฌด์—‡์„ ๋ณด๊ฑฐ๋‚˜ ๋ฌด์—‡์„ ํ–ˆ๋Š”์ง€๋Š” ์•Œ๋ ค์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
* @param {string} content_name - ํŽ˜์ด์ง€/์ œํ’ˆ์˜ ์ด๋ฆ„
* @param {string} content_category - ํŽ˜์ด์ง€/์ œํ’ˆ์˜ ์นดํ…Œ๊ณ ๋ฆฌ
* @param {number[]} content_ids - ์ด๋ฒคํŠธ์™€ ์—ฐ๊ฒฐ๋œ ์ œํ’ˆ ID(์˜ˆ: SKU(['ABC123', 'XYZ789'] ๋“ฑ))
* @param {string} content_type- ์ „๋‹ฌ๋œ content_ids ๋˜๋Š” contents๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ product ๋˜๋Š” product_group.
* @param {string} currency - value์— ์ง€์ •๋œ ํ†ตํ™”
* @param {number} value -๋น„์ฆˆ๋‹ˆ์Šค์—์„œ ์ด ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰ํ•œ ์‚ฌ์šฉ์ž์˜ ๊ฐ€์น˜
*/
viewContent = (params: Analytics.ViewContent['Fbq']) => {
this.fbq('track', 'ViewContent', params);
};

consultingApply = () => {
window.fbq('track', 'Lead', { content_name: 'ConsultingApply' });
/**
* ๊ฒ€์ƒ‰
* @param {string} content_name - ํŽ˜์ด์ง€/์ œํ’ˆ์˜ ์ด๋ฆ„
* @param {string} content_category - ํŽ˜์ด์ง€/์ œํ’ˆ์˜ ์นดํ…Œ๊ณ ๋ฆฌ
* @param {number[]} content_ids - ์ด๋ฒคํŠธ์™€ ์—ฐ๊ฒฐ๋œ ์ œํ’ˆ ID(์˜ˆ: SKU(['ABC123', 'XYZ789'] ๋“ฑ))
* @param {string} content_type- ์ „๋‹ฌ๋œ content_ids ๋˜๋Š” contents๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ product ๋˜๋Š” product_group.
* @param {string} currency - value์— ์ง€์ •๋œ ํ†ตํ™”
* @param {number} value -๋น„์ฆˆ๋‹ˆ์Šค์—์„œ ์ด ์ด๋ฒคํŠธ๋ฅผ ์‹คํ–‰ํ•œ ์‚ฌ์šฉ์ž์˜ ๊ฐ€์น˜
*/
search = (params: Analytics.Search['Fbq']) => {
this.fbq('track', 'Search', params);
};

requestApply = () => {
window.fbq('track', 'Lead', { content_name: 'RequestApply' });
};
/**
* Facebook ํ”ฝ์…€ ์Šคํฌ๋ฆฝํŠธ์™€ noscript ํƒœ๊ทธ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
* @returns Facebook ํ”ฝ์…€ ์Šคํฌ๋ฆฝํŠธ์™€ noscript ํƒœ๊ทธ์— ๋Œ€ํ•œ JSX ์š”์†Œ์ž…๋‹ˆ๋‹ค.
*/

FacebookSetter = () => {
return (
<>
<script
dangerouslySetInnerHTML={{
__html: `
<script
dangerouslySetInnerHTML={{
__html: `
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
Expand All @@ -54,20 +97,9 @@ export class FacebookAnalytics {
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '${this.key}');
fbq('track', 'PageView');
`,
}}
/>
<noscript>
<img
alt="facebook-pixel"
height="1"
width="1"
style={{ display: 'none' }}
src={`https://www.facebook.com/tr?id=${this.key}&ev=PageView&noscript=1`}
/>
</noscript>
</>
}}
/>
);
};
}
39 changes: 18 additions & 21 deletions src/utils/analytics/google.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
/**
* @brief Google analytics event๊ฐ€ ์ •์˜ ๋œ class์ž…๋‹ˆ๋‹ค.
* @description Google ์• ๋„๋ฆฌํ‹ฑ์Šค์—์„œ ์ž๋™์œผ๋กœ ์ˆ˜์ง‘๋˜๋Š” ์ •๋ณด ์™ธ์— ์ถ”๊ฐ€๋กœ ์ •๋ณด๋ฅผ ์ˆ˜์ง‘ํ•˜๊ฑฐ๋‚˜ ์• ๋„๋ฆฌํ‹ฑ์Šค์˜ ํŠน์ • ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
* @see Docs https://developers.google.com/analytics/devguides/collection/ga4/events?hl=ko&client_type=gtag
*/
import { Analytics } from './types';
import { analyticsValidCheckHandler } from './utils/valid-check-with-proxy';

export class GoogleAnalytics {
public googleAnalytics: Gtag.Gtag = typeof window !== "undefined" ? window.gtag : () => {};
private ga: Gtag.Gtag = () => {};

constructor(private key: string) {
constructor(private key?: string) {
if (!key) {
console.warn('GA ํ‚ค ์„ค์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.');
return;
}
this.key = key;
this.ga = new Proxy(
{ gtag: typeof window !== 'undefined' ? window.gtag : () => {} },
analyticsValidCheckHandler,
).gtag;
}

completeRegistration = (social: string) => {
this.googleAnalytics('event', 'CompleteRegistration', { social });
completeRegistration = (params: Analytics.CompleteRegistration['Ga']) => {
this.ga('event', 'sign_up', params);
};

startProject = (params: { id: string; step: string }) => {
this.googleAnalytics('event', 'StartProject', params);
viewContent = (params: Analytics.ViewContent['Ga']) => {
this.ga('event', 'view_item', params);
};

completeProject = (id: string) => {
this.googleAnalytics('event', 'CompleteProject', { id });
};

consultingApply = () => {
this.googleAnalytics('event', 'ConsultingApply');
};

requestApply = () => {
this.googleAnalytics('event', 'RequestApply');
login = () => {
this.ga('event', 'login');
};

GASetter = () => {
Expand Down
Loading

0 comments on commit c06d0c9

Please sign in to comment.