Skip to content

Commit de7a688

Browse files
authored
chore(rwa): add analytics (#2800)
1 parent e958fad commit de7a688

14 files changed

Lines changed: 782 additions & 4605 deletions

File tree

‎packages/apps/rwa-demo/package.json‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"version": "0.1.6",
44
"private": true,
55
"scripts": {
6-
"build": "pnpm run generate & next build",
6+
"prebuild": "pnpm run generate",
7+
"build": "next build",
78
"dev": "next dev",
89
"generate": "pactjs contract-generate --contract \"coin\" --api \"https://api.testnet.chainweb.com/chainweb/0.0/testnet04/chain/0/pact\"",
910
"generate:sdk": "cache-sh -i \"{codegen-sdk.yml,./node_modules/@kadena/graph/generated-schema.graphql,src/**/*.graph.ts,src/__generated__/**}\" -- graphql-codegen --config codegen-sdk.yml",
@@ -17,6 +18,7 @@
1718
},
1819
"dependencies": {
1920
"@apollo/client": "~3.9.11",
21+
"@google-analytics/data": "~3.2.2",
2022
"@graphql-yoga/apollo-link": "~3.3.0",
2123
"@hookform/resolvers": "^3.2.0",
2224
"@kadena/client": "workspace:*",
@@ -52,6 +54,7 @@
5254
"@kadena/pactjs-cli": "workspace:*",
5355
"@kadena/pactjs-generator": "workspace:*",
5456
"@testing-library/react-hooks": "^8.0.1",
57+
"@types/gtag.js": "~0.0.12",
5558
"@types/node": "^20.12.7",
5659
"@types/react": "^18.2.79",
5760
"@types/react-dom": "^18.2.25",

‎packages/apps/rwa-demo/src/app/(app)/layout.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010

1111
import { ActiveTransactionsList } from '@/components/ActiveTransactionsList/ActiveTransactionsList';
1212
import { AssetInfo } from '@/components/AssetInfo/AssetInfo';
13+
import { CookieConsent } from '@/components/CookieConsent/CookieConsent';
1314
import { DemoBanner } from '@/components/DemoBanner/DemoBanner';
1415
import { FrozenInvestorBanner } from '@/components/FrozenInvestorBanner/FrozenInvestorBanner';
1516
import { GasPayableBanner } from '@/components/GasPayableBanner/GasPayableBanner';
@@ -93,6 +94,7 @@ const RootLayout = ({
9394
topBanner={
9495
<Stack width="100%" gap="xs" flexDirection="column">
9596
<DemoBanner />
97+
<CookieConsent />
9698
<GraphOnlineBanner />
9799
<FrozenInvestorBanner />
98100
<GasPayableBanner />

‎packages/apps/rwa-demo/src/app/(loggedout)/layout.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import { CookieConsent } from '@/components/CookieConsent/CookieConsent';
34
import { GasPayableBanner } from '@/components/GasPayableBanner/GasPayableBanner';
45
import { Card, Stack, Text } from '@kadena/kode-ui';
56
import React from 'react';
@@ -25,6 +26,7 @@ const RootLayout = ({
2526
>
2627
<Stack flexDirection="column" className={cardWrapperClass}>
2728
<Card className={cardClass}>
29+
<CookieConsent />
2830
<GasPayableBanner />
2931
{children}
3032
</Card>

‎packages/apps/rwa-demo/src/app/layout.tsx‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { mediaProviderStyles } from '@kadena/kode-ui';
44
import React from 'react';
55

6+
import { Analytics } from '@/components/Analytics/Analytics';
67
import { Providers } from './Providers';
78

89
const RootLayout = ({
@@ -20,7 +21,10 @@ const RootLayout = ({
2021
/>
2122
</head>
2223
<body>
23-
<Providers>{children}</Providers>
24+
<Providers>
25+
<Analytics />
26+
{children}
27+
</Providers>
2428
</body>
2529
</html>
2630
);

‎packages/apps/rwa-demo/src/components/AccountProvider/AccountProvider.tsx‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export const AccountProvider: FC<PropsWithChildren> = ({ children }) => {
123123

124124
const selectAccount = (account: IWalletAccount) => {
125125
setAccount(account);
126+
126127
localStorage.setItem(getAccountCookieName(), JSON.stringify(account)!);
127128
router.replace('/');
128129
};
@@ -174,7 +175,7 @@ export const AccountProvider: FC<PropsWithChildren> = ({ children }) => {
174175
localStorage.removeItem(getAccountCookieName());
175176
}
176177
}
177-
}, []);
178+
}, [account?.address]);
178179

179180
const initProps = async (accountProp?: IWalletAccount) => {
180181
if (!accountProp) {
@@ -196,21 +197,19 @@ export const AccountProvider: FC<PropsWithChildren> = ({ children }) => {
196197
};
197198

198199
useEffect(() => {
199-
if (accountRoles.isMounted) {
200-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
201-
initProps(account);
202-
}
203-
}, [accountRoles.isMounted]);
200+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
201+
initProps(account);
202+
}, [account?.address]);
204203

205204
useEffect(() => {
206-
if (!account) {
205+
if (!account?.address) {
207206
setIsAgentState(false);
208207
setIsOwnerState(false);
209208
setIsComplianceOwnerState(false);
210209
setIsInvestorState(false);
211210
return;
212211
}
213-
}, [account]);
212+
}, [account?.address]);
214213

215214
const sign = async (tx: IUnsignedCommand): Promise<ICommand | undefined> => {
216215
const { message, close } = await getWalletConnection();

‎packages/apps/rwa-demo/src/components/AccountProvider/utils.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export async function getWalletConnection(page: string = '') {
9090
throw new Error('TIMEOUT');
9191
}),
9292
]).catch(async () => {
93+
console.log(walletUrl());
9394
wallet.location.href = walletUrl();
9495
// todo: replace this by a better way to know when the wallet is ready
9596
return waitForWallet();
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { analyticsPageView } from '@/utils/analytics';
2+
import { env } from '@/utils/env';
3+
import { usePathname } from 'next/navigation';
4+
import Script from 'next/script';
5+
import type { FC } from 'react';
6+
import React, { useEffect } from 'react';
7+
8+
export const Analytics: FC = () => {
9+
const pathname = usePathname();
10+
// 👇 send page views when users gets to the landing page
11+
useEffect(() => {
12+
if (!env.TRACKING_ID) return;
13+
14+
gtag('config', env.TRACKING_ID, {
15+
// eslint-disable-next-line @typescript-eslint/naming-convention
16+
send_page_view: false, //manually send page views to have full control
17+
});
18+
}, []);
19+
20+
useEffect(() => {
21+
if (!env.TRACKING_ID) return;
22+
analyticsPageView({
23+
page_path: pathname ?? window.location.pathname,
24+
send_to: env.TRACKING_ID,
25+
});
26+
}, [pathname]);
27+
28+
if (!env.TRACKING_ID) {
29+
return null;
30+
}
31+
return (
32+
<>
33+
<Script
34+
rel="dns-prefetch"
35+
src={`https://www.googletagmanager.com/gtag/js?id=${env.TRACKING_ID}`}
36+
></Script>
37+
<Script
38+
id="gtag-init"
39+
dangerouslySetInnerHTML={{
40+
__html: `
41+
window.dataLayer = window.dataLayer || [];
42+
function gtag(){dataLayer.push(arguments);}
43+
gtag('js', new Date());
44+
45+
46+
47+
gtag('consent', 'default', {
48+
'analytics_storage': 'denied'
49+
});
50+
51+
gtag('config', '${env.TRACKING_ID}', {
52+
'debug_mode': false
53+
});
54+
`,
55+
}}
56+
/>
57+
</>
58+
);
59+
};
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { updateConsent } from '@/utils/analytics';
2+
import { MonoCheck, MonoClose, MonoCookie } from '@kadena/kode-icons';
3+
import {
4+
Notification,
5+
NotificationButton,
6+
NotificationFooter,
7+
NotificationHeading,
8+
Text,
9+
} from '@kadena/kode-ui';
10+
import type { FC } from 'react';
11+
import React, { useCallback, useEffect, useState } from 'react';
12+
import { containerClass, notificationWrapperClass } from './styles.css';
13+
14+
export const CookieConsent: FC = () => {
15+
const [cookieConsent, setCookieConsent] = useState<boolean | null>(null);
16+
const [mounted, setMounted] = useState<boolean>(false);
17+
18+
useEffect(() => {
19+
setMounted(true);
20+
const stickyValue = localStorage.getItem('cookie_consent');
21+
if (stickyValue === null) return;
22+
setCookieConsent(JSON.parse(stickyValue));
23+
}, []);
24+
25+
useEffect(() => {
26+
if (cookieConsent === null) return;
27+
updateConsent(cookieConsent);
28+
}, [cookieConsent]);
29+
30+
const handleAccept = useCallback(() => {
31+
setCookieConsent(true);
32+
}, []);
33+
34+
const handleReject = useCallback(() => {
35+
setCookieConsent(false);
36+
}, []);
37+
38+
if (cookieConsent !== null || !mounted) return null;
39+
40+
return (
41+
<section aria-labelledby="cookie-heading" className={containerClass}>
42+
<div className={notificationWrapperClass}>
43+
<Notification
44+
intent="info"
45+
type="inlineStacked"
46+
icon={<MonoCookie />}
47+
role="none"
48+
>
49+
<NotificationHeading id="cookie-heading">
50+
Cookie Consent
51+
</NotificationHeading>
52+
<Text variant="ui">
53+
This notification concerns the cookie policy requirement to ask
54+
users for their consent to use <strong>Google Analytics</strong> or
55+
other tracking tools for better optimizations/performances.
56+
</Text>
57+
<NotificationFooter>
58+
<NotificationButton
59+
intent={'positive'}
60+
onClick={handleAccept}
61+
icon={<MonoCheck />}
62+
>
63+
Accept
64+
</NotificationButton>
65+
<NotificationButton
66+
intent={'negative'}
67+
onClick={handleReject}
68+
icon={<MonoClose />}
69+
>
70+
Reject
71+
</NotificationButton>
72+
</NotificationFooter>
73+
</Notification>
74+
</div>
75+
</section>
76+
);
77+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { atoms } from '@kadena/kode-ui/styles';
2+
import { style } from '@vanilla-extract/css';
3+
4+
export const containerClass = style([
5+
atoms({
6+
backgroundColor: 'semantic.info.default',
7+
}),
8+
{
9+
position: 'relative',
10+
top: 'unset',
11+
zIndex: 9999,
12+
},
13+
]);
14+
15+
export const notificationWrapperClass = style([
16+
{
17+
marginInline: 'auto',
18+
},
19+
]);

0 commit comments

Comments
 (0)