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

Update payload of collection search analytics events #3957

Merged
merged 2 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
13 changes: 10 additions & 3 deletions frontend/src/components/VImageCell/VImageCell.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,19 @@
<script lang="ts">
import { computed, defineComponent, PropType } from "vue"

import { useContext } from "@nuxtjs/composition-api"

import type { AspectRatio, ImageDetail } from "~/types/media"
import type { ResultKind } from "~/types/result"
import { useImageCellSize } from "~/composables/use-image-cell-size"
import { useI18n } from "~/composables/use-i18n"
import { useAnalytics } from "~/composables/use-analytics"

import { IMAGE } from "~/constants/media"

import { useSensitiveMedia } from "~/composables/use-sensitive-media"

import { useSearchStore } from "~/stores/search"

import VLicense from "~/components/VLicense/VLicense.vue"
import VLink from "~/components/VLink.vue"

Expand Down Expand Up @@ -182,7 +185,8 @@ export default defineComponent({
})
})

const { sendCustomEvent } = useAnalytics()
const { $sendCustomEvent } = useContext()
Comment on lines -185 to +188
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

const searchStore = useSearchStore()

/**
* If the user left clicks on a search result, send
Expand All @@ -194,7 +198,7 @@ export default defineComponent({
return
}

sendCustomEvent("SELECT_SEARCH_RESULT", {
$sendCustomEvent("SELECT_SEARCH_RESULT", {
id: props.image.id,
kind: props.kind,
mediaType: IMAGE,
Expand All @@ -203,6 +207,9 @@ export default defineComponent({
relatedTo: props.relatedTo,
sensitivities: props.image.sensitivity?.join(",") ?? "",
isBlurred: shouldBlur.value,
collectionType:
searchStore.strategy !== "default" ? searchStore.strategy : null,
collectionValue: searchStore.collectionValue,
})
}

Expand Down
10 changes: 10 additions & 0 deletions frontend/src/components/VLoadMore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
</VButton>
</div>
</template>

<script lang="ts">
import {
computed,
Expand All @@ -34,6 +35,8 @@ import { defineEvent } from "~/types/emits"
import type { ResultKind } from "~/types/result"
import type { SupportedSearchType } from "~/constants/media"

import { useSearchStore } from "~/stores/search"

import VButton from "~/components/VButton.vue"

export default defineComponent({
Expand Down Expand Up @@ -67,15 +70,22 @@ export default defineComponent({
const route = useRoute()
const i18n = useI18n()
const mediaStore = useMediaStore()
const searchStore = useSearchStore()
const { $sendCustomEvent } = useContext()

const { currentPage } = storeToRefs(mediaStore)

const eventPayload = computed(() => {
let kind: ResultKind =
searchStore.strategy === "default" ? "search" : "collection"
return {
searchType: props.searchType,
query: props.searchTerm,
resultPage: currentPage.value || 1,
kind,
collectionType:
searchStore.strategy !== "default" ? searchStore.strategy : null,
collectionValue: searchStore.collectionValue,
}
})

Expand Down
15 changes: 11 additions & 4 deletions frontend/src/components/VSearchResultsGrid/VAudioResult.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
<script lang="ts">
import { defineComponent, PropType, toRefs } from "vue"

import { useAnalytics } from "~/composables/use-analytics"
import { useContext } from "@nuxtjs/composition-api"

import { useAudioSnackbar } from "~/composables/use-audio-snackbar"
import { useSensitiveMedia } from "~/composables/use-sensitive-media"
import { AUDIO } from "~/constants/media"
Expand All @@ -27,6 +28,8 @@ import type { AudioTrackClickEvent } from "~/types/events"
import type { AudioDetail } from "~/types/media"
import type { ResultKind } from "~/types/result"

import { useSearchStore } from "~/stores/search"

import VAudioTrack from "~/components/VAudioTrack/VAudioTrack.vue"

export default defineComponent({
Expand Down Expand Up @@ -59,7 +62,8 @@ export default defineComponent({
},
},
setup(props) {
const { sendCustomEvent } = useAnalytics()
const { $sendCustomEvent } = useContext()
const searchStore = useSearchStore()

const { audio } = toRefs(props)
const { isHidden: shouldBlur } = useSensitiveMedia(audio)
Expand All @@ -74,7 +78,7 @@ export default defineComponent({
return
}
useAudioSnackbar().hide()
sendCustomEvent("SELECT_SEARCH_RESULT", {
$sendCustomEvent("SELECT_SEARCH_RESULT", {
id: audio.id,
kind: props.kind,
mediaType: AUDIO,
Expand All @@ -83,6 +87,9 @@ export default defineComponent({
relatedTo: props.relatedTo,
sensitivities: audio.sensitivity?.join(",") ?? "",
isBlurred: shouldBlur.value,
collectionType:
searchStore.strategy !== "default" ? searchStore.strategy : null,
collectionValue: searchStore.collectionValue,
})
}
const sendInteractionEvent = (
Expand All @@ -94,7 +101,7 @@ export default defineComponent({
: props.layout === "box"
? "VAllResultsGrid"
: "AudioSearch"
sendCustomEvent("AUDIO_INTERACTION", { ...data, component })
$sendCustomEvent("AUDIO_INTERACTION", { ...data, component })
}

return {
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/stores/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,27 @@ export const useSearchStore = defineStore("search", {
searchTypeIsSupported(state) {
return isSearchTypeSupported(state.searchType)
},
/**
* Returns the unique string representation of the current collection
* when making collection searches.
*/
collectionValue(): null | string {
if (this.collectionParams === null) {
return null
}

switch (this.collectionParams.collection) {
case "creator": {
Comment on lines +220 to +221
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been a while since I saw switch-case because the object access pattern {}[] appears so much more often. Nice!

return `${this.collectionParams.source}/${this.collectionParams.creator}`
}
case "source": {
return this.collectionParams.source
}
case "tag": {
return this.collectionParams.tag
}
}
},
},
actions: {
getApiRequestQuery(mediaType: SupportedMediaType) {
Expand Down
24 changes: 21 additions & 3 deletions frontend/src/types/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type { FilterCategory } from "~/constants/filters"
import { ResultKind } from "~/types/result"

import { RequestKind } from "./fetch-state"
import { Collection } from "./search"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the previous imports use relative path, while we usually use absolute. I'd prefer to use absolute paths everywhere (and add import type if it's a type)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, it feels weird that ESLint didn't catch and report this. We should look into that, but separately from this PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, nice catch! These were auto imports from vscode so I didn't even check them. I'll fix


export type AudioInteraction = "play" | "pause" | "seek"
export type AudioInteractionData = Exclude<
Expand All @@ -20,6 +21,19 @@ export type AudioComponent =
| "AudioSearch"
| "AudioDetailPage"
| "VAllResultsGrid"

/**
* Common properties related to searches
* on collection pages, added in the
* "Additional Search Views" project.
*/
type CollectionProperties = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

/** If a collection page, the type of collection */
collectionType: Collection | null
/** A string representing a unique identifier for the collection */
collectionValue: string | null
}

/**
* Compound type of all custom events sent from the site; Index with `EventName`
* to get the type of the payload for a specific event.
Expand Down Expand Up @@ -101,11 +115,13 @@ export type Events = {
REACH_RESULT_END: {
/** The media type being searched */
searchType: SupportedSearchType
/** The kind of search reached (a collection, a standard search view, etc.) */
kind: ResultKind
/** The search term */
query: string
/** The current page of results the user is on. */
resultPage: number
}
} & CollectionProperties
/**
* Description: The user clicks the CTA button to the external source to use the image
* Questions:
Expand Down Expand Up @@ -269,7 +285,7 @@ export type Events = {
sensitivities: string
/** whether the result was blurred or visible when selected by the user */
isBlurred: boolean | null
}
} & CollectionProperties
/**
* Description: When a user opens the external sources popover.
* Questions:
Expand Down Expand Up @@ -297,12 +313,14 @@ export type Events = {
LOAD_MORE_RESULTS: {
/** The media type being searched */
searchType: SearchType
/** The kind of search (a collection, a standard search view, etc.) */
kind: ResultKind
/** The search term */
query: string
/** The current page of results the user is on,
* *before* loading more results.. */
resultPage: number
}
} & CollectionProperties
/**
* Description: Whenever the user sets a filter. Filter category and key are the values used in code, not the user-facing filter labels.
* Questions:
Expand Down
4 changes: 4 additions & 0 deletions frontend/test/playwright/e2e/all-results-analytics.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ test.describe("all results grid analytics test", () => {
provider: "jamendo",
sensitivities: "",
isBlurred: false,
collectionType: null,
collectionValue: null,
})
})

Expand All @@ -64,6 +66,8 @@ test.describe("all results grid analytics test", () => {
relatedTo: null,
sensitivities: "",
isBlurred: false,
collectionType: null,
collectionValue: null,
})
})

Expand Down
2 changes: 2 additions & 0 deletions frontend/test/playwright/e2e/audio-detail.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,7 @@ test("sends SELECT_SEARCH_RESULT event on related audio click", async ({
query: "",
sensitivities: "",
isBlurred: false,
collectionType: null,
collectionValue: null,
})
})
2 changes: 2 additions & 0 deletions frontend/test/playwright/e2e/image-detail.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,7 @@ test("sends SELECT_SEARCH_RESULT event on related image click", async ({
query: "",
sensitivities: "",
isBlurred: false,
collectionType: null,
collectionValue: null,
})
})
6 changes: 6 additions & 0 deletions frontend/test/playwright/e2e/load-more.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ test.describe("Load more button", () => {
query: "cat",
searchType: "all",
resultPage: 1,
collectionType: null,
collectionValue: null,
})
})

Expand All @@ -177,6 +179,8 @@ test.describe("Load more button", () => {
query: "cat",
searchType: "all",
resultPage: 1,
collectionType: null,
collectionValue: null,
})
})

Expand All @@ -202,6 +206,8 @@ test.describe("Load more button", () => {
query: "cat",
searchType: "all",
resultPage: index + 1,
collectionType: null,
collectionValue: null,
})
)
})
Expand Down
Loading