Skip to content

Commit

Permalink
feat: Add tracking to banner button (#665)
Browse files Browse the repository at this point in the history
* feat: Add tracking to banner button

* fix: Package.json

* fix: Move onClick handler to a component
  • Loading branch information
LautaroPetaccio authored Jan 22, 2025
1 parent 25cd94f commit a3a9b2e
Show file tree
Hide file tree
Showing 12 changed files with 77 additions and 22 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"decentraland-crypto-fetch": "^2.0.1",
"decentraland-transactions": "^2.18.0",
"decentraland-ui": "^6.11.0",
"decentraland-ui2": "^0.9.2",
"decentraland-ui2": "^0.10.0",
"ethers": "^5.6.8",
"events": "^3.3.0",
"flat": "^5.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/containers/Banner/Banner.container.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { connect } from 'react-redux'
import { Banner } from 'decentraland-ui2'
import {
getBanner,
getBannerAssets,
getError,
isLoading
} from '../../modules/campaign'
import { MapStateProps, OwnProps } from './Banner.types'
import { Banner } from './Banner'

const mapState = (state: any, ownProps: OwnProps): MapStateProps => ({
fields: getBanner(state, ownProps.id) ?? null,
Expand Down
32 changes: 32 additions & 0 deletions src/containers/Banner/Banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { useCallback } from 'react'
import { Banner as BannerComponent } from 'decentraland-ui2'
import { getAnalytics } from '../../modules/analytics/utils'
import { BannerProps } from './Banner.types'
import { sleep } from '../../lib/time'

export const Banner: React.FC<BannerProps> = (props: BannerProps) => {
const { fields, id, ...rest } = props
const handleClick = useCallback(
(event: React.MouseEvent<HTMLButtonElement>) => {
const anchorEvent = (event as unknown) as React.MouseEvent<
HTMLAnchorElement
>
anchorEvent.preventDefault()

const analytics = getAnalytics()
if (analytics) {
analytics.track('CLICK_BANNER', {
id: fields?.id,
location: id
})
}
// Delay the navigation to allow the analytics to be tracked
sleep(300).then(() => {
window.location.href = (anchorEvent.target as HTMLAnchorElement).href
})
},
[fields?.id, id]
)

return <BannerComponent onClick={handleClick} fields={fields} {...rest} />
}
13 changes: 9 additions & 4 deletions src/containers/Banner/Banner.types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { BannerProps as UIBannerProps } from "decentraland-ui2"
import { BannerFields } from '@dcl/schemas'
import { BannerProps as UIBannerProps } from 'decentraland-ui2'

export type BannerProps = UIBannerProps & { id: string }
export type BannerProps = Omit<UIBannerProps, 'fields'> & {
fields: (BannerFields & { id: string }) | null
} & { id: string }
export type OwnProps = Pick<BannerProps, 'id'>
export type MapStateProps = Pick<BannerProps, 'fields' | 'assets' | 'isLoading' | 'error'>

export type MapStateProps = Pick<
BannerProps,
'fields' | 'assets' | 'isLoading' | 'error'
>
6 changes: 6 additions & 0 deletions src/lib/time.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export function fromMillisecondsToSeconds(timeInMilliseconds: number): number {
return Math.floor(timeInMilliseconds / 1000)
}

export function sleep(delay: number) {
return new Promise(resolve => {
setTimeout(resolve, delay)
})
}
2 changes: 1 addition & 1 deletion src/modules/campaign/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const FETCH_CAMPAIGN_FAILURE = '[Failure] Fetch Campaign'
export const fetchCampaignRequest = () => action(FETCH_CAMPAIGN_REQUEST)

export const fetchCampaignSuccess = (
banners: Record<string, BannerFields>,
banners: Record<string, BannerFields & { id: string }>,
assets: Record<string, ContentfulAsset>,
name?: LocalizedField<string>,
tabName?: LocalizedField<string>,
Expand Down
5 changes: 4 additions & 1 deletion src/modules/campaign/sagas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ describe('when handling the fetch campaign request', () => {
.put(
fetchCampaignSuccess(
{
marketplaceHomepageBanner: { ...mockHomepageBannerEntry.fields }
marketplaceHomepageBanner: {
...mockHomepageBannerEntry.fields,
id: mockHomepageBannerEntry.sys.id
}
},
{
[marketplaceHomepageBannerAssets[0].sys.id]:
Expand Down
7 changes: 5 additions & 2 deletions src/modules/campaign/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,15 @@ export function* campaignSagas(
bannerEntry &&
bannerEntry.sys.contentType.sys.id === BANNER_CONTENT_TYPE
) {
acc[key] = (bannerEntry.fields as unknown) as BannerFields
acc[key] = {
...bannerEntry.fields,
id: linkedEntryId
} as BannerFields & { id: string }
}
}
return acc
},
{} as Record<string, BannerFields>
{} as Record<string, BannerFields & { id: string }>
)

const campaignField = Object.values(items[0].fields).find(field => {
Expand Down
5 changes: 3 additions & 2 deletions src/modules/campaign/selectors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type MockState = {

let mockState: MockState
let mockAsset: ContentfulAsset
let mockBanner: BannerFields
let mockBanner: BannerFields & { id: string }

describe('Campaign selectors', () => {
beforeEach(() => {
Expand Down Expand Up @@ -68,6 +68,7 @@ describe('Campaign selectors', () => {
}

mockBanner = {
id: 'someId',
fullSizeBackground: {
'en-US': {
sys: {
Expand All @@ -77,7 +78,7 @@ describe('Campaign selectors', () => {
}
}
}
} as BannerFields
} as BannerFields & { id: string }

mockState = {
campaign: {
Expand Down
15 changes: 10 additions & 5 deletions src/modules/campaign/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { isLoadingType, type LoadingState } from '../loading'
import { CampaignState } from './types'
import { FETCH_CAMPAIGN_REQUEST } from './actions'

const isLocalizedField = (value: any): value is LocalizedField<any> => typeof value === 'object' && value !== null && 'en-US' in value

export const getState = (state: any): CampaignState => state.campaign
export const getData = (state: any): CampaignState['data'] | null => getState(state).data
export const getLoading = (state: any): LoadingState => getState(state).loading
Expand All @@ -19,7 +21,7 @@ export const getAllTags = (state: any): string[] => {
}
export const getAssets = (state: any): Record<string, ContentfulAsset> | null => getData(state)?.assets || null
export const getTabName = (state: any): LocalizedField<string> | null => getData(state)?.tabName || null
export const getBanner = (state: any, id: string): BannerFields | null => {
export const getBanner = (state: any, id: string): BannerFields & { id: string } | null => {
return getData(state)?.banners[id] ?? null
}
export const getBannerAssets = (state: any, bannerId: string): Record<string, ContentfulAsset> => {
Expand All @@ -29,10 +31,13 @@ export const getBannerAssets = (state: any, bannerId: string): Record<string, Co
if (!banner) return {}

return Object.entries(banner).reduce((acc, [_, value]) => {
if (isSysLink(value['en-US'])) {
const asset = assets?.[value['en-US'].sys.id]
if (asset) {
acc[value['en-US'].sys.id] = asset
if (isLocalizedField(value)) {
const usLocalizedValue = value['en-US']
if (isSysLink(usLocalizedValue)) {
const asset = assets?.[usLocalizedValue.sys.id]
if (asset) {
acc[usLocalizedValue.sys.id] = asset
}
}
}
return acc
Expand Down
2 changes: 1 addition & 1 deletion src/modules/campaign/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type CampaignState = {
tabName?: LocalizedField<string>
mainTag?: string
additionalTags?: string[]
banners: Record<string, BannerFields>
banners: Record<string, BannerFields & { id: string }>
assets: Record<string, ContentfulAsset>
} | null
loading: LoadingState
Expand Down

0 comments on commit a3a9b2e

Please sign in to comment.