@netlify/spark-ui 0.0.46-alpha.3 → 0.0.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  export default class Analytics {
2
2
  /**
3
3
  * Pushes an event payload into the dataLayer.
4
- * @param eventName e.g. 'www:search_query_changed'
4
+ * @param eventName e.g. 'www:search_new_query'
5
5
  * @param payload additional key/value data
6
6
  */
7
7
  track(eventName: string, payload?: Record<string, any>): void;
@@ -1,4 +1,5 @@
1
1
  import { default as GoogleTagManager } from './GoogleTagManager.astro';
2
+ import { default as GoogleTagManagerNoscript } from './GoogleTagManagerNoscript.astro';
2
3
  import { default as GoogleAnalytics } from './GoogleAnalytics.astro';
3
4
  import { default as Analytics } from './analytics';
4
- export { Analytics, GoogleAnalytics, GoogleTagManager };
5
+ export { Analytics, GoogleAnalytics, GoogleTagManager, GoogleTagManagerNoscript };
@@ -3,9 +3,9 @@ import { SearchState } from '../types/search.types';
3
3
  * Custom hook that logs search-related events for analytics.
4
4
  *
5
5
  * This hook tracks the following search events:
6
- * - `spark_search:query_changed`: Logs when the search query changes.
7
- * - `spark_search:no_results`: Logs when no results are found for a search.
8
- * - `spark_search:result_clicked`: Logs when a search result is clicked.
6
+ * - `search:new_query`: Logs when the search query changes.
7
+ * - `search:no_results`: Logs when no results are found for a search.
8
+ * - `search:result_selected`: Logs when a search result is clicked.
9
9
  *
10
10
  * It uses an instance of `Analytics` to track these events. The hook listens to changes in the `searchTerm` and `results` properties from the provided `SearchState`.
11
11
  *
@@ -15,7 +15,7 @@ import { SearchState } from '../types/search.types';
15
15
  * @param {boolean} [debug=false] - Flag to enable debug mode. If true, additional debug information will be sent with the event payloads.
16
16
  *
17
17
  * @returns {Object} - An object with the following function:
18
- * - `handleClick`: A callback function that should be attached to search result click events. It tracks `spark_search:result_clicked` events with the clicked result's title and URL.
18
+ * - `handleClick`: A callback function that should be attached to search result click events. It tracks `search:result_selected` events with the clicked result's title and URL.
19
19
  *
20
20
  * @example
21
21
  * const { handleClick } = useSearchLogger(searchState);
@@ -1,34 +1,34 @@
1
- import { A as k, y as h, q as m } from "../../../../chunks/hooks.module.CNV9mxng.js";
2
- class y {
1
+ import { A as y, y as h, q as k } from "../../../../chunks/hooks.module.CNV9mxng.js";
2
+ class s {
3
3
  /**
4
4
  * Pushes an event payload into the dataLayer.
5
- * @param eventName e.g. 'www:search_query_changed'
5
+ * @param eventName e.g. 'www:search_new_query'
6
6
  * @param payload additional key/value data
7
7
  */
8
- track(l, u = {}) {
9
- gtag("event", l, { ...u });
8
+ track(n, i = {}) {
9
+ typeof gtag == "function" ? gtag("event", n, { ...i }) : console.error(`gtag is not defined. Event [${n}] failed.`);
10
10
  }
11
11
  }
12
- function p(r, l) {
13
- const n = k(new y()).current;
12
+ function p(r, n) {
13
+ const l = y(new s()).current, e = (c) => c.debug_mode = !0;
14
14
  return h(() => {
15
15
  if (!(r != null && r.searchTerm)) return;
16
16
  const c = { query: r == null ? void 0 : r.searchTerm };
17
- l && (c.debug_mode = !0), n.track("spark_search:query_changed", c);
17
+ n && e(c), l.track("search:new_query", c);
18
18
  }, [r == null ? void 0 : r.searchTerm]), h(() => {
19
19
  if (!(r != null && r.results)) return;
20
20
  const c = { query: r == null ? void 0 : r.searchTerm };
21
- l && (c.debug_mode = !0), r != null && r.searchTerm && r.results.length === 0 && n.track("spark_search:no_results", c);
21
+ n && e(c), r != null && r.searchTerm && r.results.length === 0 && l.track("search:no_results", c);
22
22
  }, [r == null ? void 0 : r.results]), {
23
- handleClick: m((c) => {
24
- var i;
25
- const e = c.target.closest("a");
26
- if (!e) return;
27
- const d = (i = e.querySelector(".n-search-link-label")) == null ? void 0 : i.innerHTML, f = e.getAttribute("href"), o = {
28
- resultTitle: d,
29
- resultUrl: f
23
+ handleClick: k((c) => {
24
+ var f;
25
+ const o = c.target.closest("a");
26
+ if (!o) return;
27
+ const g = (f = o.querySelector(".n-search-link-label")) == null ? void 0 : f.innerHTML, d = o.getAttribute("href") || void 0, u = {
28
+ resultTitle: g,
29
+ resultUrl: d
30
30
  };
31
- l && (o.debug_mode = !0), n.track("spark_search:result_clicked", o);
31
+ n && e(u), l.track("search:result_selected", u);
32
32
  }, [])
33
33
  };
34
34
  }
@@ -23,3 +23,9 @@ export interface SearchState {
23
23
  results: SearchLinkProps[];
24
24
  isLoading: boolean;
25
25
  }
26
+ export interface SearchGTMObjectProps {
27
+ resultTitle?: string;
28
+ resultUrl?: string;
29
+ query?: string;
30
+ debug_mode?: boolean;
31
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@netlify/spark-ui",
3
3
  "description": "Assets, design tokens, components, and utilities",
4
- "version": "0.0.46-alpha.3",
4
+ "version": "0.0.46",
5
5
  "type": "module",
6
6
  "main": "dist/components/preact/index.js",
7
7
  "types": "dist/components/preact/index.d.ts",
@@ -1,9 +1,21 @@
1
+ ---
2
+ interface Props {
3
+ gaId: string;
4
+ }
5
+
6
+ const { gaId } = Astro.props as Props;
7
+ ---
1
8
  <!-- Google tag (gtag.js) -->
2
- <script async src="https://www.googletagmanager.com/gtag/js?id=G-X2FMMZSSS9"></script>
3
- <script>
4
- window.dataLayer = window.dataLayer || [];
5
- function gtag(){dataLayer.push(arguments);}
6
- gtag('js', new Date());
7
9
 
8
- gtag('config', 'G-X2FMMZSSS9');
9
- </script>
10
+ {gaId &&
11
+ <>
12
+ <script async src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}></script>
13
+ <script define:vars={{id: gaId}}>
14
+ window.dataLayer = window.dataLayer || [];
15
+ function gtag(){dataLayer.push(arguments);}
16
+ gtag('js', new Date());
17
+
18
+ gtag('config', id);
19
+ </script>
20
+ </>
21
+ }
@@ -1,5 +1,13 @@
1
+ ---
2
+ interface Props {
3
+ gtmId: string;
4
+ gaId: string;
5
+ }
6
+
7
+ const { gtmId, gaId } = Astro.props as Props;
8
+ ---
1
9
  <!-- Google Tag Manager -->
2
- <script>
10
+ {gtmId && <script define:vars={{id: gtmId}}>
3
11
  (function (w, d, s, l, i) {
4
12
  w[l] = w[l] || [];
5
13
  w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
@@ -9,15 +17,15 @@
9
17
  j.async = true;
10
18
  j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
11
19
  f.parentNode.insertBefore(j, f);
12
- })(window, document, 'script', 'dataLayer', 'GTM-T7WNFLD');
13
- </script>
20
+ })(window, document, 'script', 'dataLayer', id);
21
+ </script>}
14
22
  <!-- End Google Tag Manager -->
15
23
 
16
24
  <!-- Google Analytics (gtag.js) -->
17
- <script>
25
+ {gaId && <script define:vars={{id: gaId}}>
18
26
  function gtag(){dataLayer.push(arguments);}
19
27
  gtag('js', new Date());
20
28
 
21
- gtag('config', 'G-X2FMMZSSS9');
22
- </script>
29
+ gtag('config', id);
30
+ </script>}
23
31
  <!-- End Google Analytics (gtag.js) -->
@@ -0,0 +1,12 @@
1
+ {
2
+ Astro.props.gtmId && (
3
+ <noscript>
4
+ <iframe
5
+ src={`https://www.googletagmanager.com/ns.html?id=${Astro.props.gtmId}`}
6
+ height="0"
7
+ width="0"
8
+ style="display:none;visibility:hidden"
9
+ ></iframe>
10
+ </noscript>
11
+ )
12
+ }
@@ -1,10 +1,16 @@
1
1
  export default class Analytics {
2
+
2
3
  /**
3
4
  * Pushes an event payload into the dataLayer.
4
- * @param eventName e.g. 'www:search_query_changed'
5
+ * @param eventName e.g. 'www:search_new_query'
5
6
  * @param payload additional key/value data
6
7
  */
7
8
  track(eventName: string, payload: Record<string, any> = {}): void {
8
- gtag('event', eventName, { ...payload });
9
+ // Ensures that gtag is available before pushing events
10
+ if (typeof gtag === 'function') {
11
+ gtag('event', eventName, { ...payload });
12
+ } else {
13
+ console.error(`gtag is not defined. Event [${eventName}] failed.`);
14
+ }
9
15
  }
10
- }
16
+ }
@@ -1,5 +1,6 @@
1
1
  import GoogleTagManager from "./GoogleTagManager.astro";
2
+ import GoogleTagManagerNoscript from "./GoogleTagManagerNoscript.astro";
2
3
  import GoogleAnalytics from "./GoogleAnalytics.astro";
3
4
  import Analytics from "./analytics"
4
5
 
5
- export { Analytics, GoogleAnalytics, GoogleTagManager }
6
+ export { Analytics, GoogleAnalytics, GoogleTagManager, GoogleTagManagerNoscript }
@@ -1,4 +1,4 @@
1
- import type { SearchState } from '../types/search.types';
1
+ import type { SearchState, SearchGTMObjectProps } from '../types/search.types';
2
2
  import { useEffect, useRef, useCallback } from 'preact/hooks';
3
3
  import Analytics from '../../../../analytics/analytics';
4
4
 
@@ -6,9 +6,9 @@ import Analytics from '../../../../analytics/analytics';
6
6
  * Custom hook that logs search-related events for analytics.
7
7
  *
8
8
  * This hook tracks the following search events:
9
- * - `spark_search:query_changed`: Logs when the search query changes.
10
- * - `spark_search:no_results`: Logs when no results are found for a search.
11
- * - `spark_search:result_clicked`: Logs when a search result is clicked.
9
+ * - `search:new_query`: Logs when the search query changes.
10
+ * - `search:no_results`: Logs when no results are found for a search.
11
+ * - `search:result_selected`: Logs when a search result is clicked.
12
12
  *
13
13
  * It uses an instance of `Analytics` to track these events. The hook listens to changes in the `searchTerm` and `results` properties from the provided `SearchState`.
14
14
  *
@@ -18,7 +18,7 @@ import Analytics from '../../../../analytics/analytics';
18
18
  * @param {boolean} [debug=false] - Flag to enable debug mode. If true, additional debug information will be sent with the event payloads.
19
19
  *
20
20
  * @returns {Object} - An object with the following function:
21
- * - `handleClick`: A callback function that should be attached to search result click events. It tracks `spark_search:result_clicked` events with the clicked result's title and URL.
21
+ * - `handleClick`: A callback function that should be attached to search result click events. It tracks `search:result_selected` events with the clicked result's title and URL.
22
22
  *
23
23
  * @example
24
24
  * const { handleClick } = useSearchLogger(searchState);
@@ -31,16 +31,16 @@ export function useSearchLogger(state?: SearchState, debug?: boolean) {
31
31
  const ref = useRef<Analytics>(new Analytics());
32
32
  const analytics = ref.current;
33
33
 
34
+ const enableDebugger = (o: SearchGTMObjectProps) => o.debug_mode = true
35
+
34
36
  // Log search query
35
37
  useEffect(() => {
36
38
  if (!state?.searchTerm) return;
37
39
  const payload = { query: state?.searchTerm };
38
40
 
39
- if (debug) {
40
- payload.debug_mode = true;
41
- }
41
+ if (debug) enableDebugger(payload)
42
42
 
43
- analytics.track('spark_search:query_changed', payload);
43
+ analytics.track('search:new_query', payload);
44
44
  }, [state?.searchTerm]);
45
45
 
46
46
  // Log zero‑hit searches
@@ -49,12 +49,10 @@ export function useSearchLogger(state?: SearchState, debug?: boolean) {
49
49
 
50
50
  const payload = { query: state?.searchTerm };
51
51
 
52
- if (debug) {
53
- payload.debug_mode = true;
54
- }
52
+ if (debug) enableDebugger(payload)
55
53
 
56
54
  if (state?.searchTerm && state.results.length === 0) {
57
- analytics.track('spark_search:no_results', payload);
55
+ analytics.track('search:no_results', payload);
58
56
  }
59
57
  }, [state?.results]);
60
58
 
@@ -64,17 +62,16 @@ export function useSearchLogger(state?: SearchState, debug?: boolean) {
64
62
  if (!anchor) return;
65
63
 
66
64
  const label = anchor.querySelector('.n-search-link-label')?.innerHTML;
67
- const url = anchor.getAttribute('href');
65
+ const url = anchor.getAttribute('href') || undefined;
68
66
  const payload = {
69
67
  resultTitle: label,
70
68
  resultUrl: url,
71
69
  };
72
70
 
73
- if (debug) {
74
- payload.debug_mode = true;
75
- }
71
+ if (debug) enableDebugger(payload)
72
+
76
73
 
77
- analytics.track('spark_search:result_clicked', payload);
74
+ analytics.track('search:result_selected', payload);
78
75
  }, []);
79
76
 
80
77
  return {
@@ -27,3 +27,10 @@ export interface SearchState {
27
27
  results: SearchLinkProps[];
28
28
  isLoading: boolean;
29
29
  }
30
+
31
+ export interface SearchGTMObjectProps {
32
+ resultTitle?: string;
33
+ resultUrl?: string;
34
+ query?: string;
35
+ debug_mode?: boolean;
36
+ }