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

Add VIEW_EXTERNAL_SOURCES event #2450

Merged
merged 12 commits into from
Jul 3, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,16 @@
<script lang="ts">
import { computed, defineComponent, PropType, ref, SetupContext } from "vue"

import { storeToRefs } from "pinia"

import { defineEvent } from "~/types/emits"

import { useUiStore } from "~/stores/ui"
import { useSearchStore } from "~/stores/search"
import { useMediaStore } from "~/stores/media"

import { useDialogControl } from "~/composables/use-dialog-control"
import { useAnalytics } from "~/composables/use-analytics"

import type { MediaType } from "~/constants/media"
import type { ExternalSource } from "~/types/external-source"
Expand Down Expand Up @@ -130,6 +135,8 @@ export default defineComponent({
const sectionRef = ref<HTMLElement | null>(null)
const triggerRef = ref<InstanceType<typeof VButton> | null>(null)
const uiStore = useUiStore()
const searchStore = useSearchStore()
const { sendCustomEvent } = useAnalytics()

const isMd = computed(() => uiStore.isBreakpoint("md"))

Expand All @@ -139,6 +146,9 @@ export default defineComponent({

const isVisible = ref(false)

const mediaStore = useMediaStore()
const { currentPage } = storeToRefs(mediaStore)

const {
close: closeDialog,
open: openDialog,
Expand All @@ -151,6 +161,17 @@ export default defineComponent({
emit: emit as SetupContext["emit"],
})

const eventedOnTriggerClick = () => {
if (!isVisible.value) {
sendCustomEvent("VIEW_EXTERNAL_SOURCES", {
searchType: searchStore.searchType,
zackkrida marked this conversation as resolved.
Show resolved Hide resolved
query: searchStore.searchTerm,
resultPage: currentPage.value || 1,
})
}
onTriggerClick()
}

return {
sectionRef,
triggerRef,
Expand All @@ -159,7 +180,7 @@ export default defineComponent({

closeDialog,
openDialog,
onTriggerClick,
onTriggerClick: eventedOnTriggerClick,
triggerA11yProps,

isVisible,
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/types/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,21 @@ export type Events = {
query: string
}
/**
* Description: When a user opens the external sources popover.
* Questions:
* - How often do users use this feature?
* - Under what conditions to users use this feature? No results?
* Many results, but none they actually select?
*/
VIEW_EXTERNAL_SOURCES: {
/** The media type being searched */
searchType: SearchType
/** The search term */
query: string
/** Pagination depth */
resultPage: number
}
/*
* Description: Whenever the user clicks the load more button
* Questions:
* - On what page do users typically find a result?
Expand Down
59 changes: 32 additions & 27 deletions frontend/test/playwright/e2e/external-sources.spec.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,43 @@
import { test, expect } from "@playwright/test"

import { goToSearchTerm, setCookies } from "~~/test/playwright/utils/navigation"

test("sends analytics event on external source click", async ({ page }) => {
let eventData: {
name: string
mediaType: string
query: string
} = { name: "", mediaType: "", query: "" }
page.on("request", (req) => {
if (req.method() === "POST") {
const requestData = req.postDataJSON()
if (requestData?.n == "SELECT_EXTERNAL_SOURCE") {
eventData = JSON.parse(requestData?.p)
}
}
})
// Start waiting for new page before clicking.
import { test } from "@playwright/test"

import { goToSearchTerm } from "~~/test/playwright/utils/navigation"

import {
collectAnalyticsEvents,
expectEventPayloadToMatch,
} from "~~/test/playwright/utils/analytics"

test("sends correct analytics events", async ({ page, context }) => {
const pagePromise = page.context().waitForEvent("page")

const mediaType = "image"
const name = "Centre For Ageing Better"
const query = "cat"
const events = collectAnalyticsEvents(context)

await setCookies(page.context(), { analytics: "true" })
await goToSearchTerm(page, "cat", { mode: "SSR", query: "ff_analytics=on" })
await goToSearchTerm(page, "cat", { mode: "SSR" })

await page.getByRole("button", { name: "Source list" }).click()
await page.getByRole("link", { name: "Centre for Ageing Better" }).click()

const newPage = await pagePromise
await newPage.close()

expect(eventData.name).toEqual(name)
expect(eventData.mediaType).toEqual(mediaType)
expect(eventData.query).toEqual(query)
const viewEvent = events.find((event) => event.n === "VIEW_EXTERNAL_SOURCES")
const selectEvent = events.find(
(event) => event.n === "SELECT_EXTERNAL_SOURCE"
)

if (!viewEvent || !selectEvent) {
throw new Error("Analytics events were not triggered properly.")
}

expectEventPayloadToMatch(viewEvent, {
searchType: "all",
query: "cat",
resultPage: 1,
})
expectEventPayloadToMatch(selectEvent, {
name: "Centre For Ageing Better",
mediaType: "image",
query: "cat",
component: "VExternalSourceList",
})
})