Track clicks from feed

This commit is contained in:
James Grugett 2022-04-19 00:16:08 -05:00
parent a6e6e2f52f
commit 280ae97070
9 changed files with 70 additions and 33 deletions

12
common/tracking.ts Normal file
View File

@ -0,0 +1,12 @@
export type View = {
contractId: string
timestamp: number
}
export type UserEvent = ClickEvent
export type ClickEvent = {
type: 'click'
contractId: string
timestamp: number
}

View File

@ -1,4 +0,0 @@
export type View = {
contractId: string
timestamp: number
}

View File

@ -26,6 +26,10 @@ service cloud.firestore {
allow create: if userId == request.auth.uid;
}
match /private-users/{userId}/events/{eventId} {
allow create: if userId == request.auth.uid;
}
match /contracts/{contractId} {
allow read;
allow update: if request.resource.data.diff(resource.data).affectedKeys()

View File

@ -46,7 +46,6 @@ export function ContractActivity(props: {
return (
<FeedItems
contract={contract}
user={user}
items={items}
className={className}
betRowClassName={betRowClassName}

View File

@ -45,19 +45,19 @@ import { AnswerBetPanel } from '../answers/answer-bet-panel'
import { useSaveSeenContract } from '../../hooks/use-seen-contracts'
import { User } from '../../../common/user'
import { Modal } from '../layout/modal'
import { trackClick } from '../../lib/firebase/tracking'
export function FeedItems(props: {
contract: Contract
user: User | null | undefined
items: ActivityItem[]
className?: string
betRowClassName?: string
}) {
const { contract, user, items, className, betRowClassName } = props
const { contract, items, className, betRowClassName } = props
const { outcomeType } = contract
const ref = useRef<HTMLDivElement | null>(null)
useSaveSeenContract(ref, contract, user)
useSaveSeenContract(ref, contract)
return (
<div className={clsx('flow-root pr-2 md:pr-0', className)} ref={ref}>
@ -347,6 +347,7 @@ export function FeedQuestion(props: {
href={
props.contractPath ? props.contractPath : contractPath(contract)
}
onClick={() => trackClick(contract.id)}
className="text-lg text-indigo-700 sm:text-xl"
>
{question}

View File

@ -4,9 +4,10 @@ import Link from 'next/link'
export const SiteLink = (props: {
href: string
children?: any
onClick?: () => void
className?: string
}) => {
const { href, children, className } = props
const { href, children, onClick, className } = props
return href.startsWith('http') ? (
<a
@ -17,7 +18,10 @@ export const SiteLink = (props: {
)}
style={{ /* For iOS safari */ wordBreak: 'break-word' }}
target="_blank"
onClick={(e) => e.stopPropagation()}
onClick={(e) => {
e.stopPropagation()
if (onClick) onClick()
}}
>
{children}
</a>
@ -29,7 +33,10 @@ export const SiteLink = (props: {
className
)}
style={{ /* For iOS safari */ wordBreak: 'break-word' }}
onClick={(e) => e.stopPropagation()}
onClick={(e) => {
e.stopPropagation()
if (onClick) onClick()
}}
>
{children}
</a>

View File

@ -1,8 +1,7 @@
import _ from 'lodash'
import { useEffect, RefObject, useState } from 'react'
import { Contract } from '../../common/contract'
import { User } from '../../common/user'
import { logView } from '../lib/firebase/views'
import { trackView } from '../lib/firebase/tracking'
import { useIsVisible } from './use-is-visible'
export const useSeenContracts = () => {
@ -19,8 +18,7 @@ export const useSeenContracts = () => {
export const useSaveSeenContract = (
ref: RefObject<Element>,
contract: Contract,
user: User | null | undefined
contract: Contract
) => {
const isVisible = useIsVisible(ref)
@ -32,9 +30,9 @@ export const useSaveSeenContract = (
}
localStorage.setItem(key, JSON.stringify(newSeenContracts))
if (user) logView(user.id, contract.id)
trackView(contract.id)
}
}, [isVisible, contract, user])
}, [isVisible, contract])
}
const key = 'feed-seen-contracts'

View File

@ -0,0 +1,36 @@
import { doc, collection, setDoc } from 'firebase/firestore'
import _ from 'lodash'
import { db } from './init'
import { ClickEvent, View } from '../../../common/tracking'
import { listenForLogin, User } from './users'
let user: User | null = null
if (typeof window !== 'undefined') {
listenForLogin((u) => (user = u))
}
export async function trackView(contractId: string) {
if (!user) return
const ref = doc(collection(db, 'private-users', user.id, 'views'))
const view: View = {
contractId,
timestamp: Date.now(),
}
return await setDoc(ref, view)
}
export async function trackClick(contractId: string) {
if (!user) return
const ref = doc(collection(db, 'private-users', user.id, 'events'))
const clickEvent: ClickEvent = {
type: 'click',
contractId,
timestamp: Date.now(),
}
return await setDoc(ref, clickEvent)
}

View File

@ -1,16 +0,0 @@
import { doc, collection, setDoc } from 'firebase/firestore'
import _ from 'lodash'
import { db } from './init'
import { View } from '../../../common/view'
export async function logView(userId: string, contractId: string) {
const ref = doc(collection(db, 'private-users', userId, 'views'))
const view: View = {
contractId,
timestamp: Date.now(),
}
return await setDoc(ref, view)
}