Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add tracking to banner button #665

Merged
merged 3 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading