Skip to content

Commit 54648b7

Browse files
authored
Merge pull request #1481 from onflow/brian-doyle/update-events-header
Add Google Events to Header
2 parents 730a4db + 04de753 commit 54648b7

File tree

6 files changed

+152
-12
lines changed

6 files changed

+152
-12
lines changed

docusaurus.config.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ const editUrl = ({ docPath }) => {
132132
};
133133
}
134134
return acc;
135-
}, null);
135+
}, /** @type {Repository & SourceDestination | null} */ (null));
136136
if (!sourceRepository) {
137137
return `https://github.com/onflow/docs/tree/main/docs/${docPath}`;
138138
}
@@ -294,6 +294,7 @@ const config = {
294294
{
295295
type: 'custom-connectButton',
296296
position: 'right',
297+
label: 'Connect',
297298
},
298299
{
299300
href: 'https://github.com/onflow',
@@ -505,17 +506,18 @@ const config = {
505506
name: 'docusaurus-svgo',
506507
configureWebpack(config) {
507508
// allow svgr to use svgo config file
508-
for (const rule of config.module.rules) {
509+
for (const rule of config.module?.rules || []) {
509510
if (
511+
rule &&
510512
typeof rule === 'object' &&
511-
rule.test.toString() === '/\\.svg$/i'
513+
rule.test?.toString() === '/\\.svg$/i'
512514
) {
513-
for (const nestedRule of rule.oneOf) {
514-
if (nestedRule.use instanceof Array) {
515+
for (const nestedRule of rule.oneOf || []) {
516+
if (nestedRule && typeof nestedRule === 'object' && nestedRule.use instanceof Array) {
515517
for (const loader of nestedRule.use) {
516518
if (
517519
typeof loader === 'object' &&
518-
loader.loader === require.resolve('@svgr/webpack')
520+
loader?.loader === require.resolve('@svgr/webpack')
519521
) {
520522
if (typeof loader.options === 'object') {
521523
loader.options.svgoConfig = null;
@@ -531,7 +533,7 @@ const config = {
531533
'module.rules': 'replace',
532534
},
533535
module: {
534-
rules: config.module.rules,
536+
rules: config.module?.rules || [],
535537
},
536538
};
537539
},
@@ -549,8 +551,7 @@ const config = {
549551
};
550552
},
551553
/** this function needs doesn't pick up hot reload event, it needs a restart */
552-
// @ts-expect-error
553-
function (context, options) {
554+
function (context) {
554555
const { siteConfig } = context;
555556
return {
556557
name: 'docusaurus-flow-networks-plugin',

src/components/ConnectButton.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
1010
import { useProfile } from '../hooks/use-profile';
1111
import { useGithubAvatar } from '../hooks/use-github-avatar';
1212
import { SocialType } from '../types/gold-star';
13+
import { event } from '@site/src/utils/gtags.client';
14+
import { GA_EVENTS, GA_CATEGORIES } from '@site/src/constants/ga-events';
1315

1416
const shortenAddress = (address: string) => {
1517
if (!address) return '';
@@ -40,9 +42,25 @@ const ConnectButton: React.FC = () => {
4042
setIsProfileModalOpen(false);
4143
};
4244

45+
const handleSignInClick = () => {
46+
// Check if we're on the homepage
47+
const isHomepage = typeof window !== 'undefined' && window.location.pathname === '/';
48+
49+
// Track the Sign In click
50+
event({
51+
action: isHomepage ? GA_EVENTS.ACTION_CARD_CLICK : GA_EVENTS.NAV_BAR_CLICK,
52+
category: isHomepage ? GA_CATEGORIES.ACTION_CARD : GA_CATEGORIES.NAV_BAR,
53+
label: 'Nav-Sign In',
54+
location: true,
55+
});
56+
57+
// Call the original logIn function
58+
logIn();
59+
};
60+
4361
if (!user.loggedIn) {
4462
return (
45-
<Button size="sm" className="mr-2" onClick={logIn}>
63+
<Button size="sm" className="mr-2" onClick={handleSignInClick}>
4664
Sign In
4765
</Button>
4866
);

src/constants/ga-events.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
export const GA_EVENTS = {
33
// Existing events currently used in the codebase
44
ACTION_CARD_CLICK: 'action_card_click',
5+
NAV_BAR_CLICK: 'nav_bar_click',
6+
SEARCH_CLICK: 'search_click',
57
FEEDBACK_CLICK: 'feedback_click',
68
AUTH_LOGIN: 'login',
79
} as const;
810

911
// Event categories for consistent tracking - Using existing categories
1012
export const GA_CATEGORIES = {
1113
ACTION_CARD: 'action_card',
14+
NAV_BAR: 'nav_bar',
15+
SEARCH: 'search',
1216
FEEDBACK: 'feedback',
1317
AUTH: 'auth',
1418
} as const;
Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,94 @@
1+
import React from 'react';
12
import ComponentTypes from '@theme-original/NavbarItem/ComponentTypes';
23
import ConnectButton from '@site/src/components/ConnectButton';
4+
import { event } from '@site/src/utils/gtags.client';
5+
import { GA_EVENTS, GA_CATEGORIES, GA_ACTIONS } from '@site/src/constants/ga-events';
6+
7+
// Wrapper component that adds tracking to navbar items
8+
const withTracking = (Component) => {
9+
return (props) => {
10+
const handleClick = (e) => {
11+
// Extract meaningful label from props
12+
const label = props.label || 'unknown-navbar-item';
13+
14+
// Check if we're on the homepage
15+
const isHomepage = typeof window !== 'undefined' && window.location.pathname === '/';
16+
17+
// Track the navbar item click with appropriate event based on page
18+
event({
19+
action: isHomepage ? GA_EVENTS.ACTION_CARD_CLICK : GA_EVENTS.NAV_BAR_CLICK,
20+
category: isHomepage ? GA_CATEGORIES.ACTION_CARD : GA_CATEGORIES.NAV_BAR,
21+
label: label,
22+
location: true,
23+
});
24+
25+
// Call original onClick if it exists
26+
if (props.onClick) {
27+
props.onClick(e);
28+
}
29+
};
30+
31+
return <Component {...props} onClick={handleClick} />;
32+
};
33+
};
34+
35+
// Create tracked versions of all component types
36+
const trackedComponentTypes = {};
37+
Object.keys(ComponentTypes).forEach(key => {
38+
trackedComponentTypes[key] = withTracking(ComponentTypes[key]);
39+
});
40+
41+
// Add specific wrapper for html type navbar items
42+
const withHtmlTracking = (Component) => {
43+
return (props) => {
44+
const handleClick = (e) => {
45+
// Debug: log all available props
46+
47+
// Try to get the label from various sources
48+
let label = props.label || props.item?.label;
49+
50+
// If no label in props, try to extract from HTML span
51+
if (!label && props.html) {
52+
const spanMatch = props.html.match(/<span[^>]*>([^<]+)<\/span>/);
53+
if (spanMatch) {
54+
label = spanMatch[1].trim();
55+
}
56+
}
57+
58+
// Final fallback
59+
if (!label) {
60+
label = 'unknown-html-item';
61+
}
62+
63+
// Add Nav- prefix to match existing pattern
64+
const prefixedLabel = `Nav-${label}`;
65+
66+
// Check if we're on the homepage
67+
const isHomepage = typeof window !== 'undefined' && window.location.pathname === '/';
68+
69+
// Track the navbar item click with appropriate event based on page
70+
event({
71+
action: isHomepage ? GA_EVENTS.ACTION_CARD_CLICK : GA_EVENTS.NAV_BAR_CLICK,
72+
category: isHomepage ? GA_CATEGORIES.ACTION_CARD : GA_CATEGORIES.NAV_BAR,
73+
label: prefixedLabel,
74+
location: true,
75+
});
76+
77+
// Call original onClick if it exists
78+
if (props.onClick) {
79+
props.onClick(e);
80+
}
81+
};
82+
83+
return <Component {...props} onClick={handleClick} />;
84+
};
85+
};
386

487
export default {
5-
...ComponentTypes,
88+
...trackedComponentTypes,
689
'custom-connectButton': ConnectButton,
90+
// Add html type if it exists
91+
...(ComponentTypes.html ? { html: withHtmlTracking(ComponentTypes.html) } : {}),
92+
// Add default type if it exists (for href items)
93+
...(ComponentTypes.default ? { default: withHtmlTracking(ComponentTypes.default) } : {}),
794
};

src/theme/SearchBar.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,30 @@ import React from 'react';
22
import SearchBar from '@theme-original/SearchBar';
33
import AskCookbook from '@cookbookdev/docsbot/react';
44
import BrowserOnly from '@docusaurus/BrowserOnly';
5+
import { event } from '@site/src/utils/gtags.client';
6+
import { GA_EVENTS, GA_CATEGORIES } from '@site/src/constants/ga-events';
57
/** It's a public API key, so it's safe to expose it here */
68
const COOKBOOK_PUBLIC_API_KEY =
79
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NzEyYWRkYjk5YjBmNWViM2ZkODQxOGMiLCJpYXQiOjE3MjkyNzc0MDMsImV4cCI6MjA0NDg1MzQwM30._bhlmAnFpvxvkTV0PvU-6FwabhFOdSOx-qed2UIogpY';
810
export default function SearchBarWrapper(props) {
11+
const handleSearchClick = () => {
12+
// Check if we're on the homepage
13+
const isHomepage = typeof window !== 'undefined' && window.location.pathname === '/';
14+
15+
// Track the search bar click
16+
event({
17+
action: isHomepage ? GA_EVENTS.ACTION_CARD_CLICK : GA_EVENTS.SEARCH_CLICK,
18+
category: isHomepage ? GA_CATEGORIES.ACTION_CARD : GA_CATEGORIES.SEARCH,
19+
label: 'Nav-Search',
20+
location: true,
21+
});
22+
};
23+
924
return (
1025
<>
11-
<SearchBar {...props} />
26+
<div onClick={handleSearchClick}>
27+
<SearchBar {...props} />
28+
</div>
1229
<BrowserOnly>
1330
{() => <AskCookbook apiKey={COOKBOOK_PUBLIC_API_KEY} />}
1431
</BrowserOnly>

src/ui/design-system/src/lib/Pages/HomePage/BrowseByCategory.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import React from 'react';
2+
import { event } from '@site/src/utils/gtags.client';
3+
import { GA_EVENTS, GA_CATEGORIES } from '@site/src/constants/ga-events';
24

35
const CATEGORIES = [
46
{
@@ -92,6 +94,16 @@ const CATEGORIES = [
9294
];
9395

9496
const BrowseByCategory: React.FC = () => {
97+
const handleLinkClick = (label: string, href: string, category: string) => {
98+
event({
99+
action: GA_EVENTS.ACTION_CARD_CLICK,
100+
category: GA_CATEGORIES.ACTION_CARD,
101+
label: `${category} - ${label}`,
102+
location: true,
103+
href: href,
104+
});
105+
};
106+
95107
return (
96108
<section className="container mx-auto py-12">
97109
<h2 className="text-2xl md:text-3xl font-bold text-gray-900 dark:text-white mb-8">Browse by Category</h2>
@@ -106,6 +118,7 @@ const BrowseByCategory: React.FC = () => {
106118
href={link.href}
107119
target={link.href.startsWith('http') ? '_blank' : undefined}
108120
rel={link.href.startsWith('http') ? 'noopener noreferrer' : undefined}
121+
onClick={() => handleLinkClick(link.label, link.href, cat.title)}
109122
className="text-base text-gray-800 dark:text-gray-100 hover:text-primary-green-500 dark:hover:text-primary-green-300 transition-colors"
110123
>
111124
{link.label}

0 commit comments

Comments
 (0)