mirror of
https://github.com/placeholder-soft/web.git
synced 2026-06-13 00:18:40 +08:00
Feat/add events to docs (#587)
* Created logEvent utility * Added event tracking to OCS Banner * Created CustomNavbarLink with event tracking * created custom navbar dropdown link with event tracking * added event tracking to P0 navbar elements * Added eventDetail parameter to event tracking * Updated Bootcamp link * enforced cursor pointer on custom navbar links * updated navbar elements to include event tracking * event tracking for navbar social links * added target property to custom navbar elements * made links to off-domain locations open in new tab * updated tutorials data * implemented tracking on connect wallet buttons * removed duplicate connect button from StudentProgress component * Links now send events with high importance * Cleaned up StudentProgress component * Social clicks use useCallback * bugfix for logEvent * created callbacks for social click handlers * improved social click callbacks * updated event names * updated connect wallet event names on base.org * added full typing to logEvent utility * refactored logEvent typing * added userId to event data options * updated base-docs logEvent immplementations * updated Connect Wallet event for base.org * changed component_type to the expected * Updated event logging for onchain summer banner
This commit is contained in:
committed by
GitHub
parent
c3f4ea25de
commit
100e7604fd
@@ -185,6 +185,9 @@ const config = {
|
||||
to: '/tutorials',
|
||||
navposition: 'bottomLeft',
|
||||
label: 'Tutorials',
|
||||
type: 'custom-navbarLink',
|
||||
eventLabel: 'tutorials',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
to: '/base-camp/docs/welcome',
|
||||
@@ -194,14 +197,24 @@ const config = {
|
||||
{
|
||||
label: 'Learn',
|
||||
to: '/base-camp/docs/welcome',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'camp_learn',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
label: 'Track your progress',
|
||||
to: '/base-camp/progress',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'camp_trackprogress',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
label: 'Bootcamp',
|
||||
href: 'https://base.org/bootcamp',
|
||||
to: 'https://base.org/bootcamp',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'camp_bootcamp',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -212,18 +225,30 @@ const config = {
|
||||
items: [
|
||||
{
|
||||
label: 'Apps',
|
||||
href: 'https://www.base.org/ecosystem',
|
||||
to: 'https://www.base.org/ecosystem',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'ecosystem_apps',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
label: 'Grants',
|
||||
href: 'https://paragraph.xyz/@grants.base.eth/calling-based-builders',
|
||||
to: 'https://paragraph.xyz/@grants.base.eth/calling-based-builders',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'ecosystem_grants',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Bridge',
|
||||
navposition: 'topRight',
|
||||
href: 'https://bridge.base.org/',
|
||||
to: 'https://bridge.base.org/',
|
||||
target: '_blank',
|
||||
type: 'custom-navbarLink',
|
||||
eventLabel: 'bridge',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
type: 'dropdown',
|
||||
@@ -232,15 +257,27 @@ const config = {
|
||||
items: [
|
||||
{
|
||||
label: 'Block Explorer',
|
||||
href: 'https://base.blockscout.com/',
|
||||
to: 'https://base.blockscout.com/',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'builders_blockexplorer',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
label: 'Status',
|
||||
href: 'https://status.base.org/',
|
||||
to: 'https://status.base.org/',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'builders_status',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
label: 'Bug Bounty',
|
||||
href: 'https://hackerone.com/coinbase',
|
||||
to: 'https://hackerone.com/coinbase',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'builders_bugbounty',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -251,15 +288,27 @@ const config = {
|
||||
items: [
|
||||
{
|
||||
label: 'Mission',
|
||||
href: 'https://www.base.org/about',
|
||||
to: 'https://www.base.org/about',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'about_mission',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
label: 'Blog',
|
||||
href: 'https://base.mirror.xyz/',
|
||||
to: 'https://base.mirror.xyz/',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'about_blog',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
{
|
||||
label: 'Jobs',
|
||||
href: 'https://www.base.org/jobs',
|
||||
to: 'https://www.base.org/jobs',
|
||||
target: '_blank',
|
||||
type: 'custom-dropdownLink',
|
||||
eventLabel: 'about_jobs',
|
||||
eventContext: 'navbar',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { useLocalStorage } from 'usehooks-ts';
|
||||
import { useCallback } from 'react';
|
||||
import Icon from '../Icon';
|
||||
import logEvent, {ActionType, AnalyticsEventImportance, ComponentType} from "base-ui/utils/logEvent";
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
@@ -10,6 +11,17 @@ const href = 'https://www.base.org/onchainsummer?utm_source=DocsSite&utm_campaig
|
||||
export function OcsBanner() {
|
||||
const [isBannerVisible, setIsBannerVisible] = useLocalStorage('isOcsBannerVisible', true);
|
||||
|
||||
const linkClick = useCallback(() => {
|
||||
logEvent(
|
||||
'ocsbanner',
|
||||
{
|
||||
action: ActionType.click,
|
||||
componentType: ComponentType.banner,
|
||||
context: 'navbar'
|
||||
},
|
||||
AnalyticsEventImportance.low
|
||||
)}, [logEvent, ActionType, ComponentType, AnalyticsEventImportance]);
|
||||
|
||||
const hideBanner = useCallback(() => {
|
||||
setIsBannerVisible(false);
|
||||
}, [setIsBannerVisible]);
|
||||
@@ -26,6 +38,7 @@ export function OcsBanner() {
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
aria-label="Onchain Summer Buildathon Banner"
|
||||
onClick={linkClick}
|
||||
>
|
||||
<span className={styles.bannerText}>Join the Onchain Summer Buildathon!</span>
|
||||
</a>
|
||||
@@ -35,6 +48,7 @@ export function OcsBanner() {
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
aria-label="Onchain Summer Buildathon Banner"
|
||||
onClick={linkClick}
|
||||
>
|
||||
<span className={styles.bannerSpacer} />
|
||||
</a>
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/* eslint-disable */
|
||||
import React from 'react';
|
||||
import { useState } from 'react';
|
||||
import { ConnectButton } from '@rainbow-me/rainbowkit';
|
||||
import { useAccount } from 'wagmi';
|
||||
|
||||
import useNFTData from '../../utils/nft-exercise-data';
|
||||
|
||||
import NFTCard from './NFTCard';
|
||||
|
||||
export default function StudentProgress() {
|
||||
@@ -105,19 +103,6 @@ export default function StudentProgress() {
|
||||
>
|
||||
<h1 style={{ paddingBottom: '40px' }}>Base Camp Progress</h1>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
width: 'auto',
|
||||
flexBasis: '50%',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-end',
|
||||
gap: '0.5rem',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<ConnectButton />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{renderNFTProgressContainer()}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useThemeConfig, ErrorCauseBoundary } from '@docusaurus/theme-common';
|
||||
import { useNavbarMobileSidebar } from '@docusaurus/theme-common/internal';
|
||||
import NavbarItem from '@theme/NavbarItem';
|
||||
@@ -11,6 +11,7 @@ import styles from './styles.module.css';
|
||||
|
||||
import Icon from '../../../components/Icon';
|
||||
import { CustomConnectButton } from '../../NavbarItem/ComponentTypes';
|
||||
import logEvent, { ActionType, AnalyticsEventImportance, ComponentType } from "base-ui/utils/logEvent";
|
||||
|
||||
function useNavbarItems() {
|
||||
// TODO temporary casting until ThemeConfig type is improved
|
||||
@@ -39,6 +40,42 @@ ${JSON.stringify(item, null, 2)}`,
|
||||
);
|
||||
}
|
||||
function NavbarLayoutTopContent({ left, right }) {
|
||||
const discordClick = useCallback(() => {
|
||||
logEvent(
|
||||
'social_discord',
|
||||
{
|
||||
action: ActionType.click,
|
||||
component: ComponentType.icon,
|
||||
context: 'navbar',
|
||||
},
|
||||
AnalyticsEventImportance.low
|
||||
);
|
||||
}, [logEvent])
|
||||
|
||||
const twitterClick = useCallback(() => {
|
||||
logEvent(
|
||||
'social_twitter',
|
||||
{
|
||||
action: ActionType.click,
|
||||
component: ComponentType.icon,
|
||||
context: 'navbar',
|
||||
},
|
||||
AnalyticsEventImportance.low
|
||||
); }, [logEvent])
|
||||
|
||||
const githubClick = useCallback(() => {
|
||||
logEvent(
|
||||
'social_github',
|
||||
{
|
||||
action: ActionType.click,
|
||||
component: ComponentType.icon,
|
||||
context: 'navbar',
|
||||
},
|
||||
AnalyticsEventImportance.low
|
||||
);
|
||||
}, [logEvent])
|
||||
|
||||
|
||||
return (
|
||||
<div className="navbar__inner">
|
||||
<div className="navbar__items">{left}</div>
|
||||
@@ -50,6 +87,7 @@ function NavbarLayoutTopContent({ left, right }) {
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
aria-label="Base on Discord"
|
||||
onClick={discordClick}
|
||||
>
|
||||
<Icon name="discord" />
|
||||
</a>
|
||||
@@ -58,6 +96,7 @@ function NavbarLayoutTopContent({ left, right }) {
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
aria-label="Base on Twitter"
|
||||
onClick={twitterClick}
|
||||
>
|
||||
<Icon name="twitter" />
|
||||
</a>
|
||||
@@ -66,6 +105,7 @@ function NavbarLayoutTopContent({ left, right }) {
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
aria-label="Base on Github"
|
||||
onClick={githubClick}
|
||||
>
|
||||
<Icon name="github" />
|
||||
</a>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useAccount } from 'wagmi';
|
||||
|
||||
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
|
||||
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
|
||||
import LocaleDropdownNavbarItem from '@theme/NavbarItem/LocaleDropdownNavbarItem';
|
||||
@@ -11,6 +14,7 @@ import { ConnectButton } from '@rainbow-me/rainbowkit';
|
||||
import '@rainbow-me/rainbowkit/styles.css';
|
||||
import styles from './styles.module.css';
|
||||
import { WalletAvatar } from '../../components/WalletAvatar';
|
||||
import logEvent, { ActionType, AnalyticsEventImportance, ComponentType, identify } from "base-ui/utils/logEvent";
|
||||
|
||||
export const CustomConnectButton = ({ className }) => {
|
||||
return (
|
||||
@@ -18,6 +22,35 @@ export const CustomConnectButton = ({ className }) => {
|
||||
{({ account, chain, openAccountModal, openChainModal, openConnectModal, mounted }) => {
|
||||
const ready = mounted;
|
||||
const connected = ready && account && chain;
|
||||
const { address } = useAccount();
|
||||
|
||||
useEffect(() => {
|
||||
if (address) {
|
||||
logEvent(
|
||||
'wallet_connected',
|
||||
{
|
||||
action: ActionType.change,
|
||||
context: 'navbar',
|
||||
address,
|
||||
},
|
||||
AnalyticsEventImportance.low,
|
||||
);
|
||||
identify({ userId: address });
|
||||
}
|
||||
}, [address]);
|
||||
|
||||
const clickConnect = useCallback(() => {
|
||||
openConnectModal?.();
|
||||
logEvent(
|
||||
'connect_wallet',
|
||||
{
|
||||
action: ActionType.click,
|
||||
componentType: ComponentType.button,
|
||||
context: 'navbar',
|
||||
},
|
||||
AnalyticsEventImportance.low,
|
||||
);
|
||||
}, [openConnectModal]);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -34,7 +67,7 @@ export const CustomConnectButton = ({ className }) => {
|
||||
{(() => {
|
||||
if (!connected) {
|
||||
return (
|
||||
<button className={styles.connectButton} onClick={openConnectModal} type="button">
|
||||
<button className={styles.connectButton} onClick={clickConnect} type="button">
|
||||
Connect
|
||||
</button>
|
||||
);
|
||||
@@ -106,6 +139,56 @@ export const CustomConnectButton = ({ className }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const CustomNavbarLink = (props) => {
|
||||
return (
|
||||
<a
|
||||
href={props.to}
|
||||
target={props.target ?? '_self'}
|
||||
className='navbar__item navbar__link'
|
||||
style={{ cursor: 'pointer'}}
|
||||
onClick={() => {
|
||||
logEvent(
|
||||
props.eventLabel,
|
||||
{
|
||||
action: ActionType.click,
|
||||
componentType: ComponentType.link,
|
||||
context: props.eventContext,
|
||||
},
|
||||
AnalyticsEventImportance.high
|
||||
)
|
||||
}}
|
||||
>
|
||||
{props.label}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
export const CustomDropdownLink = (props) => {
|
||||
return (
|
||||
<li>
|
||||
<a
|
||||
href={props.to}
|
||||
target={props.target ?? '_self'}
|
||||
className='dropdown__link'
|
||||
style={{ cursor: 'pointer'}}
|
||||
onClick={() => {
|
||||
logEvent(
|
||||
props.eventLabel,
|
||||
{
|
||||
action: ActionType.click,
|
||||
componentType: ComponentType.link,
|
||||
context: props.eventContext,
|
||||
},
|
||||
AnalyticsEventImportance.high
|
||||
)
|
||||
}}
|
||||
>
|
||||
{props.label}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
const ComponentTypes = {
|
||||
default: DefaultNavbarItem,
|
||||
localeDropdown: LocaleDropdownNavbarItem,
|
||||
@@ -117,5 +200,7 @@ const ComponentTypes = {
|
||||
docsVersion: DocsVersionNavbarItem,
|
||||
docsVersionDropdown: DocsVersionDropdownNavbarItem,
|
||||
'custom-connectWallet': CustomConnectButton,
|
||||
'custom-navbarLink': CustomNavbarLink,
|
||||
'custom-dropdownLink': CustomDropdownLink,
|
||||
};
|
||||
export default ComponentTypes;
|
||||
|
||||
@@ -213,6 +213,32 @@
|
||||
"duration": "8 min read",
|
||||
"checksum": "527200e33d612b0c76e5eaacddfc23633b57eaa4577f389d4429b8f862c45462"
|
||||
},
|
||||
"thirdweb-unreal-nft-items": {
|
||||
"title": "Thirdweb and Unreal - NFT Items",
|
||||
"slug": "/thirdweb-unreal-nft-items",
|
||||
"description": "Learn how to use NFTs as in-game items using Thirdweb and Unreal.",
|
||||
"author": "briandoyle81",
|
||||
"keywords": [
|
||||
"Solidity",
|
||||
"ERC-721",
|
||||
"token",
|
||||
"NFT",
|
||||
"thirdweb",
|
||||
"Unreal",
|
||||
"c++",
|
||||
"blueprints",
|
||||
"onchain games"
|
||||
],
|
||||
"tags": [
|
||||
"nft"
|
||||
],
|
||||
"difficulty": "hard",
|
||||
"hide_table_of_contents": false,
|
||||
"displayed_sidebar": null,
|
||||
"last_updated": "Jun 21, 2024",
|
||||
"duration": "40 min read",
|
||||
"checksum": "cfd81fd73a2952f32fd63557915cc864aee013dca9beb255b47cde01b205b32e"
|
||||
},
|
||||
"account-abstraction-with-biconomy": {
|
||||
"title": "Account Abstraction on Base using Biconomy",
|
||||
"slug": "/account-abstraction-with-biconomy",
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { ConnectButton, useConnectModal } from '@rainbow-me/rainbowkit';
|
||||
import { UserAvatar } from 'apps/web/src/components/ConnectWalletButton/UserAvatar';
|
||||
import { ShinyButton } from 'apps/web/src/components/ShinyButton/ShinyButton';
|
||||
import logEvent, { identify } from 'apps/web/src/utils/logEvent';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useAccount } from 'wagmi';
|
||||
import { ConnectButton, useConnectModal } from '@rainbow-me/rainbowkit';
|
||||
|
||||
import { UserAvatar } from 'apps/web/src/components/ConnectWalletButton/UserAvatar';
|
||||
import { ShinyButton } from 'apps/web/src/components/ShinyButton/ShinyButton';
|
||||
import logEvent, {
|
||||
ActionType,
|
||||
AnalyticsEventImportance,
|
||||
ComponentType,
|
||||
identify,
|
||||
} from 'base-ui/utils/logEvent';
|
||||
|
||||
type ConnectWalletButtonProps = {
|
||||
color: 'white' | 'black';
|
||||
@@ -21,14 +27,30 @@ export function ConnectWalletButton({ color, className }: ConnectWalletButtonPro
|
||||
|
||||
useEffect(() => {
|
||||
if (address) {
|
||||
logEvent('connected_wallet', { address });
|
||||
logEvent(
|
||||
'wallet_connected',
|
||||
{
|
||||
action: ActionType.change,
|
||||
context: 'navbar',
|
||||
address
|
||||
},
|
||||
AnalyticsEventImportance.low
|
||||
);
|
||||
identify({ userId: address });
|
||||
}
|
||||
}, [address]);
|
||||
|
||||
const clickConnect = useCallback(() => {
|
||||
openConnectModal?.();
|
||||
logEvent('ConnectWalletButton_Clicked', {});
|
||||
logEvent(
|
||||
'connect_wallet',
|
||||
{
|
||||
action: ActionType.click,
|
||||
componentType: ComponentType.button,
|
||||
context: 'navbar'
|
||||
},
|
||||
AnalyticsEventImportance.low
|
||||
);
|
||||
}, [openConnectModal]);
|
||||
|
||||
return (
|
||||
|
||||
94
libs/base-ui/utils/logEvent.ts
Normal file
94
libs/base-ui/utils/logEvent.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
declare const window: Window &
|
||||
typeof globalThis & {
|
||||
ClientAnalytics: {
|
||||
logEvent: LogEvent;
|
||||
};
|
||||
};
|
||||
|
||||
export default function logEvent(
|
||||
name: string,
|
||||
event: CCAEventData,
|
||||
importance: AnalyticsEventImportance | undefined
|
||||
) {
|
||||
const CCA = window.ClientAnalytics;
|
||||
if (CCA) {
|
||||
CCA?.logEvent(name, event, importance);
|
||||
}
|
||||
}
|
||||
|
||||
export function identify(event: CCAEventData) {
|
||||
const CCA = window.ClientAnalytics;
|
||||
if (CCA) {
|
||||
CCA?.logEvent('identify', event, AnalyticsEventImportance.low);
|
||||
}
|
||||
}
|
||||
|
||||
type LogEvent = (
|
||||
eventName: string,
|
||||
eventData: CCAEventData,
|
||||
importance?: AnalyticsEventImportance,
|
||||
) => void;
|
||||
|
||||
enum ComponentType {
|
||||
unknown = 'unknown',
|
||||
banner = 'banner',
|
||||
button = 'button',
|
||||
card = 'card',
|
||||
chart = 'chart',
|
||||
content_script = 'content_script',
|
||||
dropdown = 'dropdown',
|
||||
link = 'link',
|
||||
page = 'page',
|
||||
modal = 'modal',
|
||||
table = 'table',
|
||||
search_bar = 'search_bar',
|
||||
service_worker = 'service_worker',
|
||||
text = 'text',
|
||||
text_input = 'text_input',
|
||||
tray = 'tray',
|
||||
checkbox = 'checkbox',
|
||||
icon = 'icon',
|
||||
}
|
||||
|
||||
enum ActionType {
|
||||
unknown = 'unknown',
|
||||
blur = 'blur',
|
||||
click = 'click',
|
||||
change = 'change',
|
||||
dismiss = 'dismiss',
|
||||
focus = 'focus',
|
||||
hover = 'hover',
|
||||
select = 'select',
|
||||
measurement = 'measurement',
|
||||
move = 'move',
|
||||
process = 'process',
|
||||
render = 'render',
|
||||
scroll = 'scroll',
|
||||
view = 'view',
|
||||
search = 'search',
|
||||
keyPress = 'keyPress',
|
||||
}
|
||||
|
||||
enum AnalyticsEventImportance {
|
||||
low = 'low',
|
||||
high = 'high',
|
||||
}
|
||||
|
||||
type CCAEventData = {
|
||||
// Standard Attributes
|
||||
action?: ActionType;
|
||||
componentType?: ComponentType;
|
||||
// Custom Attributes
|
||||
doc_helpful?: boolean;
|
||||
doc_feedback_reason?: string | null;
|
||||
page_path?: string;
|
||||
conversation_id?: number;
|
||||
message_id?: number;
|
||||
response_helpful?: boolean;
|
||||
address?: string;
|
||||
context?: string;
|
||||
userId?: string;
|
||||
};
|
||||
|
||||
export { ComponentType, ActionType, AnalyticsEventImportance };
|
||||
export type { LogEvent, CCAEventData };
|
||||
Reference in New Issue
Block a user