Skip to content

Commit

Permalink
feat(demo, bottle): GA, GTM basic config (#87)
Browse files Browse the repository at this point in the history
* feat(demo): add GA, GTM for demo

* feat(bottle): add GA, GTM for bottle
  • Loading branch information
stakbucks authored Nov 10, 2024
1 parent 93a7e15 commit a9c932d
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 2 deletions.
1 change: 1 addition & 0 deletions apps/bottle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
},
"dependencies": {
"@bottlesteam/ui": "workspace:*",
"@next/third-parties": "^15.0.3",
"@radix-ui/react-slot": "^1.1.0",
"@tanstack/react-query": "^5.51.21",
"cookies-next": "^4.2.1",
Expand Down
3 changes: 3 additions & 0 deletions apps/bottle/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AppBridgeProvider } from '@/features/app-bridge/AppBridgeProvider';
import { UserAgentProvider } from '@/features/user-agent/UserAgentProvider';
import { QueryClientProvider } from '@/store/query/QueryClientProvider';
import { GoogleAnalytics, GoogleTagManager } from '@next/third-parties/google';
import { getCookie } from 'cookies-next';
import type { Metadata } from 'next';
import './globals.css';
Expand Down Expand Up @@ -36,6 +37,8 @@ export default function RootLayout({
</UserAgentProvider>
</QueryClientProvider>
</main>
<GoogleAnalytics gaId={`${process.env.NEXT_PUBLIC_BOTTLE_GOOGLE_ANALYSTICS_ID}`} />
<GoogleTagManager gtmId={`${process.env.NEXT_PUBLIC_BOTTLE_GOOGLE_TAG_MANAGER_ID}`} />
</body>
</html>
);
Expand Down
18 changes: 17 additions & 1 deletion apps/bottle/src/app/profile/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,28 @@ import { KakaoId } from '@/components/profile/kakao-id';
import { Keywords } from '@/components/profile/keywords';
import { ProfileLayout } from '@/components/profile/layout';
import { Region } from '@/components/profile/region';
import { useDurationTime } from '@/features/analystics/useDurationTime';
import { useFunnel } from '@/features/funnel';
import { Profile } from '@/models/profile';
import { User } from '@/models/user';
import { useProfileMutation } from '@/store/mutation/useProfileMuatation';
import { useRouter } from 'next/navigation';
import { sendGTMEvent } from '@next/third-parties/google';
import { useRouter, usePathname } from 'next/navigation';
import { useMemo } from 'react';

const MAX_STEPS = 7;

type CreateProfileFunnelValues = Profile & Pick<User, 'kakaoId'>;

const EVENT_NAME = 'create_profile';

export default function CreateProfilePage() {
const router = useRouter();
const pathname = usePathname();
useDurationTime(duration => {
console.log('duration', duration);
sendGTMEvent({ duration, path: pathname }, EVENT_NAME);
});

const { onNextStep, currentStep, getValue, getValues } = useFunnel<CreateProfileFunnelValues>('/profile/create');
const { mutate } = useProfileMutation({ type: 'create' });
Expand All @@ -36,6 +45,7 @@ export default function CreateProfilePage() {
<Job
initialValue={getValue('job')}
onNext={job => {
sendGTMEvent('1->2', EVENT_NAME);
onNextStep('job', job);
}}
ctaButtonText="다음"
Expand All @@ -49,6 +59,7 @@ export default function CreateProfilePage() {
<Height
initialValue={getValue('height')}
onNext={height => {
sendGTMEvent('2->3', EVENT_NAME);
onNextStep('height', height);
}}
ctaButtonText="다음"
Expand All @@ -62,6 +73,7 @@ export default function CreateProfilePage() {
<Region
initialValue={getValue('region')}
onNext={region => {
sendGTMEvent('3->4', EVENT_NAME);
onNextStep('region', region);
}}
ctaButtonText="다음"
Expand All @@ -75,6 +87,7 @@ export default function CreateProfilePage() {
<MBTI
initialValue={getValue('mbti')}
onNext={mbti => {
sendGTMEvent('4->5', EVENT_NAME);
onNextStep('mbti', mbti);
}}
ctaButtonText="다음"
Expand All @@ -88,6 +101,7 @@ export default function CreateProfilePage() {
<Keywords
initialValue={getValue('keyword')}
onNext={keyword => {
sendGTMEvent('5->6', EVENT_NAME);
onNextStep('keyword', keyword);
}}
ctaButtonText="다음"
Expand All @@ -101,6 +115,7 @@ export default function CreateProfilePage() {
<Interests
initialValue={getValue('interest')}
onNext={interest => {
sendGTMEvent('6->7', EVENT_NAME);
onNextStep('interest', interest);
}}
ctaButtonText="다음"
Expand All @@ -114,6 +129,7 @@ export default function CreateProfilePage() {
<KakaoId
initialValue={getValue('kakaoId')}
onNext={kakaoId => {
sendGTMEvent('7->complete', EVENT_NAME);
mutate({ ...(getValues() as Profile), kakaoId });
}}
/>
Expand Down
20 changes: 20 additions & 0 deletions apps/bottle/src/features/analystics/useDurationTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useEffect, useRef } from 'react';

const MILLISECONDS_PER_SECOND = 1000;

export function useDurationTime(onEnd: (duration: number) => void) {
const timeRef = useRef<number>(0);

useEffect(() => {
const timer = setInterval(() => {
timeRef.current += 1;
}, MILLISECONDS_PER_SECOND);

return () => {
clearInterval(timer);
onEnd(timeRef.current);
};
}, [onEnd]);

return {};
}
1 change: 1 addition & 0 deletions apps/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dependencies": {
"@bottlesteam/ui": "workspace:*",
"@bottlesteam/utils": "workspace:*",
"@next/third-parties": "^15.0.3",
"@tanstack/react-query": "^5.51.21",
"cookies-next": "^4.2.1",
"es-toolkit": "^1.26.1",
Expand Down
2 changes: 2 additions & 0 deletions apps/demo/src/app/bottle/[id]/BottleDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { UserInformation } from '@/components/common/user-information';
import { Bottle } from '@/models/bottle';
import { Asset, FixedBottomCTAButton, spacings } from '@bottlesteam/ui';
import { useUserAgent } from '@bottlesteam/utils';
import { sendGTMEvent } from '@next/third-parties/google';

const ANDROID_INDENT_SCHEME = 'intent://main#Intent;scheme=bottle;package=com.team.bottles;end';
const IOS_STORE_SCHEME =
Expand All @@ -13,6 +14,7 @@ export function BottleDetail({ bottleDetail: user }: { bottleDetail: Bottle }) {
const userAgent = useUserAgent();

const handleInstall = () => {
sendGTMEvent('bottle_detail', '설치 버튼 클릭');
if (!userAgent.isMobile) {
alert('모바일에서만 설치 가능합니다.');
return;
Expand Down
2 changes: 2 additions & 0 deletions apps/demo/src/app/bottles/Bottles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import TelescopeImage from '@/assets/images/telescope.webp';
import { BottleCard } from '@/components/common/bottle-card';
import { Fallback } from '@/components/common/fallback';
import { Layout, spacings } from '@bottlesteam/ui';
import { sendGTMEvent } from '@next/third-parties/google';
import { pick } from 'es-toolkit';
import { useRouter } from 'next/navigation';
import { RandomBottlesQuery, UserInfo } from './page';
Expand All @@ -26,6 +27,7 @@ export function Bottles({ bottles: { randomBottles }, userInfo }: Props) {
<BottleCard
key={bottle.id}
onClick={() => {
sendGTMEvent('bottle', '보틀 클릭');
router.push(`/bottle/${bottle.id}`);
}}
>
Expand Down
3 changes: 3 additions & 0 deletions apps/demo/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { GoogleAnalytics, GoogleTagManager } from '@next/third-parties/google';
import type { Metadata, Viewport } from 'next';
import './globals.css';
import { wantedSansStd } from '../fonts';
Expand Down Expand Up @@ -25,6 +26,8 @@ export default function RootLayout({
<body className={wantedSansStd.className}>
<main className={layoutStyle}>{children}</main>
</body>
<GoogleAnalytics gaId={`${process.env.NEXT_PUBLIC_DEMO_GOOGLE_ANALYSTICS_ID}`} />
<GoogleTagManager gtmId={`${process.env.NEXT_PUBLIC_DEMO_GOOGLE_TAG_MANAGER_ID}`} />
</html>
);
}
2 changes: 2 additions & 0 deletions apps/demo/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import LoginBackground from '@/assets/images/login-background.webp';
import { KakaoButton } from '@/components/kakao-button';
import { Asset, Paragraph, spacings } from '@bottlesteam/ui';
import { sendGAEvent } from '@next/third-parties/google';
import Image from 'next/image';
import { useEffect } from 'react';

Expand Down Expand Up @@ -45,6 +46,7 @@ export default function Home() {
</div>
<KakaoButton
onClick={() => {
sendGAEvent('kakao login', '카카오 로그인 버튼 클릭');
Kakao.Auth.authorize({
redirectUri: REDIRECT_URI,
});
Expand Down
21 changes: 21 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
"NEXT_PUBLIC_ADMIN_ID_2",
"NEXT_PUBLIC_ADMIN_PASSWORD",
"NEXT_PUBLIC_KAKAO_CLIENT_ID",
"NEXT_PUBLIC_KAKAO_JAVASCRIPT_KEY"
"NEXT_PUBLIC_KAKAO_JAVASCRIPT_KEY",
"NEXT_PUBLIC_DEMO_GOOGLE_ANALYSTICS_ID",
"NEXT_PUBLIC_DEMO_GOOGLE_TAG_MANAGER_ID",
"NEXT_PUBLIC_BOTTLE_GOOGLE_ANALYSTICS_ID",
"NEXT_PUBLIC_BOTTLE_GOOGLE_TAG_MANAGER_ID"
],
"tasks": {
"build": {
Expand Down

0 comments on commit a9c932d

Please sign in to comment.