File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 2525 "@babel/preset-env" : " 7.29.0" ,
2626 "@babel/preset-react" : " 7.28.5" ,
2727 "@babel/preset-typescript" : " 7.28.5" ,
28- "@canonical/analytics-events" : " 1.0.4 " ,
28+ "@canonical/analytics-events" : " 1.0.5 " ,
2929 "@canonical/cookie-policy" : " 3.8.4" ,
3030 "@canonical/global-nav" : " 3.8.0" ,
3131 "@canonical/react-components" : " 3.12.1" ,
Original file line number Diff line number Diff line change @@ -2,9 +2,36 @@ import { initFSFLanguageSelect } from "./fsf-language-select";
22import nps from "./nps" ;
33import initExpandableArea from "./expandable-area" ;
44import declareGlobal from "../libs/declare" ;
5+ import { trackEvent , trackPageView } from "@canonical/analytics-events" ;
6+
7+ if ( window . ANALYTICS_ENDPOINT ) {
8+ trackPageView ( "snap_home_page" ) ;
9+ }
10+
11+ function initHomeSearchTracking ( ) : void {
12+ const form = document . querySelector (
13+ "[data-js='home-search-form']" ,
14+ ) as HTMLFormElement | null ;
15+
16+ if ( form ) {
17+ form . addEventListener ( "submit" , ( ) => {
18+ const input = form . querySelector ( "input[name='q']" ) as HTMLInputElement ;
19+ if ( input ?. value ) {
20+ const searchId = crypto . randomUUID ( ) ;
21+ sessionStorage . setItem ( "search_id" , searchId ) ;
22+
23+ trackEvent ( "snap_home_search_submitted" , {
24+ search_id : searchId ,
25+ query : input . value ,
26+ } ) ;
27+ }
28+ } ) ;
29+ }
30+ }
531
632declareGlobal ( "snapcraft.public.homepage" , {
733 initExpandableArea,
834 initFSFLanguageSelect,
35+ initHomeSearchTracking,
936 nps,
1037} ) ;
Original file line number Diff line number Diff line change 77 Row ,
88 Strip ,
99} from "@canonical/react-components" ;
10+ import { trackEvent } from "@canonical/analytics-events" ;
1011
1112import { PackageFilter } from "../PackageFilter" ;
1213
@@ -127,11 +128,26 @@ function PackageList({
127128 ) ) }
128129 { ! isFetching &&
129130 data &&
130- data . packages . map ( ( packageData : Package ) => (
131+ data . packages . map ( ( packageData : Package , index : number ) => (
131132 < Col
132133 size = { 3 }
133134 style = { { marginBottom : "1.5rem" } }
134135 key = { packageData . id }
136+ onClick = { ( ) => {
137+ const query = searchParams . get ( "q" ) ;
138+ if ( query ) {
139+ const searchId =
140+ sessionStorage . getItem ( "search_id" ) || "" ;
141+ trackEvent ( "snap_store_search_result_clicked" , {
142+ search_id : searchId ,
143+ query,
144+ position :
145+ ( parseInt ( currentPage ) - 1 ) * ITEMS_PER_PAGE +
146+ index +
147+ 1 ,
148+ } ) ;
149+ }
150+ } }
135151 >
136152 < DefaultCard data = { packageData } />
137153 </ Col >
Original file line number Diff line number Diff line change 11import { Button } from "@canonical/react-components" ;
2+ import { trackEvent } from "@canonical/analytics-events" ;
23import { useSearchParams , useNavigate , useLocation } from "react-router-dom" ;
34
45import type { RefObject } from "react" ;
@@ -27,6 +28,14 @@ export const SearchInput = ({
2728 searchParams . delete ( "page" ) ;
2829 searchParams . set ( "q" , searchRef . current . value ) ;
2930 setSearchParams ( searchParams ) ;
31+
32+ const searchId = crypto . randomUUID ( ) ;
33+ sessionStorage . setItem ( "search_id" , searchId ) ;
34+
35+ trackEvent ( "snap_store_search_submitted" , {
36+ search_id : searchId ,
37+ query : searchRef . current . value ,
38+ } ) ;
3039 }
3140 if ( searchSummaryRef && searchSummaryRef . current ) {
3241 searchSummaryRef . current . scrollIntoView ( {
Original file line number Diff line number Diff line change 11import { createRoot } from "react-dom/client" ;
22import { createBrowserRouter , RouterProvider } from "react-router-dom" ;
33import { QueryClient , QueryClientProvider } from "react-query" ;
4+ import { trackPageView } from "@canonical/analytics-events" ;
45
56import Root from "./layouts/Root" ;
67import Store from "./pages/Store" ;
78
9+ if ( window . ANALYTICS_ENDPOINT ) {
10+ trackPageView ( "snap_store_page" ) ;
11+ }
12+
813const router = createBrowserRouter ( [
914 {
1015 path : "/" ,
Original file line number Diff line number Diff line change 1- import { useRef } from "react" ;
1+ import { useEffect , useRef } from "react" ;
22import { useLocation , useSearchParams } from "react-router-dom" ;
3+ import { trackEvent } from "@canonical/analytics-events" ;
34
45import Banner from "../../components/Banner" ;
56import PackageList from "../../components/PackageList/PackageList" ;
@@ -30,6 +31,38 @@ function Store(): React.JSX.Element {
3031 const packagesCount = data ?. packages ? data ?. packages . length : 0 ;
3132 const isResultExist = status === "success" && packagesCount > 0 ;
3233
34+ useEffect ( ( ) => {
35+ if ( searchTerm && status === "success" && ! isFetching ) {
36+ let searchId = sessionStorage . getItem ( "search_id" ) ;
37+ if ( ! searchId ) {
38+ searchId = crypto . randomUUID ( ) ;
39+ sessionStorage . setItem ( "search_id" , searchId ) ;
40+ }
41+
42+ if ( packagesCount > 0 ) {
43+ trackEvent ( "snap_store_search_results_loaded" , {
44+ search_id : searchId ,
45+ query : searchTerm ,
46+ total_items : data ?. total_items ?? 0 ,
47+ page : currentPage ,
48+ } ) ;
49+ } else {
50+ trackEvent ( "snap_store_search_no_results" , {
51+ search_id : searchId ,
52+ query : searchTerm ,
53+ } ) ;
54+ }
55+ }
56+ } , [
57+ searchTerm ,
58+ status ,
59+ currentPage ,
60+ searchParams ,
61+ packagesCount ,
62+ data ,
63+ isFetching ,
64+ ] ) ;
65+
3366 const searchRef = useRef < HTMLInputElement | null > ( null ) ;
3467 const searchSummaryRef = useRef < HTMLDivElement > ( null ) ;
3568
Original file line number Diff line number Diff line change 55 < div class ="p-block ">
66 < h1 > The app store for Linux</ h1 >
77 </ div >
8- < form class ="p-search-box " action ="/store ">
8+ < form class ="p-search-box " action ="/store " data-js =" home-search-form " >
99 < label class ="u-off-screen " for ="search "> Search</ label >
1010 < input type ="search " id ="search " class ="p-search-box__input " name ="q " placeholder ="Search thousands of snaps " required ="" autocomplete ="on ">
1111 < button type ="reset " class ="p-search-box__reset "> < i class ="p-icon--close "> Close</ i > </ button >
Original file line number Diff line number Diff line change @@ -183,6 +183,10 @@ <h2>Measure user growth</h2>
183183 Sentry . captureException ( e ) ;
184184 }
185185
186+ try {
187+ snapcraft . public . homepage . initHomeSearchTracking ( ) ;
188+ } catch ( e ) { }
189+
186190 try {
187191 snapcraft . public . featuredSnaps . init ( { { featured_categories | safe } } ) ;
188192 } catch ( e ) {
Original file line number Diff line number Diff line change 924924 hashery "^1.5.0"
925925 keyv "^5.6.0"
926926
927- " @canonical/analytics-events@1.0.4 " :
928- version "1.0.4 "
929- resolved "https://registry.yarnpkg.com/@canonical/analytics-events/-/analytics-events-1.0.4 .tgz#27440161a7970f2f2a990dd0597e70685706c3b4 "
930- integrity sha512-+ChQJHpwpBQxuSdVwNv1YSGSzX6z6QeCmfxKqo8K02Hk2nJGuIdwEfi4yIa/KxVOhxaFLO7fy7ACSsBkTGeGRA ==
927+ " @canonical/analytics-events@1.0.5 " :
928+ version "1.0.5 "
929+ resolved "https://registry.yarnpkg.com/@canonical/analytics-events/-/analytics-events-1.0.5 .tgz#88a18381a657196ea5f21b5932a41c5afce69999 "
930+ integrity sha512-GMFbPJ83FcN+ItLcc1czYp0HUA96uLfu+35B0NWEVCL/Wy/CRc0o8Ab1DgAyjBw16reIP+SkAg9k/NBwNj1Tjg ==
931931
932932" @canonical/cookie-policy@3.8.4 " :
933933 version "3.8.4"
You can’t perform that action at this time.
0 commit comments