@quintype/framework 7.34.4-qlitics-removal.0 → 7.34.4

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [7.34.4](https://github.com/quintype/quintype-node-framework/compare/v7.34.3...v7.34.4) (2025-07-21)
6
+
5
7
  ### [7.34.3](https://github.com/quintype/quintype-node-framework/compare/v7.34.2...v7.34.3) (2025-07-07)
6
8
 
7
9
 
@@ -1,10 +1,84 @@
1
1
  /**
2
- * Register a page view in Google Analytics. This method takes the page object, which is usually returned from *"/route-data.json"*.
2
+ * This namespace handles a number of analytics related functions.
3
+ * The vast majority of these features are already wired by default, but and are only required to be called manually if you are doing something special.
4
+ * By default, both GA and qlitics are tracked (including when pages are loaded via AJAX).
5
+ *
6
+ * The GA tracker looks for the default tracker, then looks for the tracker called `gtm1`. If you would like to disable GA tracking, set `window.qtNoAutomaticGATracking` to true.
7
+ *
8
+ * ```javascript
9
+ * import * from "@quintype/framework/client/analytics";
10
+ * ```
11
+ * @category Client
12
+ * @module analytics
13
+ */
14
+
15
+ import get from "lodash/get";
16
+ import { runWhenIdle } from "./impl/run-when-idle";
17
+
18
+ /**
19
+ * Load qlitics.js. This should be done automatically for you
20
+ * @returns {void}
21
+ */
22
+ // istanbul ignore next
23
+ export function startAnalytics({ mountAt = global.qtMountAt || "" } = {}) {
24
+ global.qlitics =
25
+ global.qlitics ||
26
+ function () {
27
+ (qlitics.q = qlitics.q || []).push(arguments);
28
+ };
29
+ global.qlitics("init");
30
+
31
+ runWhenIdle(function () {
32
+ const s = document.createElement("script");
33
+ s.type = "text/javascript";
34
+ s.async = true;
35
+ s.src = `${mountAt}/qlitics.js`;
36
+ const x = document.getElementsByTagName("script")[0];
37
+ x.parentNode.insertBefore(s, x);
38
+ });
39
+ }
40
+
41
+ function pageTypeToQliticsPageType(pageType) {
42
+ switch (pageType) {
43
+ case "story-page":
44
+ return "story";
45
+ case "home-page":
46
+ return "home";
47
+ case "section-page":
48
+ return "section";
49
+ case "tag-page":
50
+ return "topic";
51
+ default:
52
+ return pageType;
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Register a story view event. This should already be wired up for story pages, but this event can
58
+ * be fired on an infinite scroll event. Ideally, please use {@link registerPageView}
59
+ * @param {uuid} storyContentId
60
+ * @returns {void}
61
+ */
62
+ export function registerStoryView(storyContentId) {
63
+ global.qlitics("track", "story-view", {
64
+ "story-content-id": storyContentId,
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Register a page view in both qlitics and google analytics. This method takes the page object, which is usually returned from *"/route-data.json"*.
3
70
  * @param {Object} page ex: *{"page-type": "story-page", "story": {...}}*
4
71
  * @param {string} newPath ex: "/path/to/story"
5
72
  * @returns {void}
6
73
  */
7
74
  export function registerPageView(page, newPath) {
75
+ global.qlitics("track", "page-view", {
76
+ "page-type": pageTypeToQliticsPageType(page.pageType),
77
+ });
78
+ if (page.pageType == "story-page") {
79
+ registerStoryView(get(page.data, ["story", "id"]));
80
+ }
81
+
8
82
  if (newPath && global.ga && !global.qtNoAutomaticGATracking) {
9
83
  global.ga(function (tracker) {
10
84
  tracker = tracker || global.ga.getByName("gtm1");
@@ -14,3 +88,27 @@ export function registerPageView(page, newPath) {
14
88
  });
15
89
  }
16
90
  }
91
+
92
+ /**
93
+ * Set the current member id on qlitics
94
+ * @param {number} memberId The member id of the logged in member
95
+ * @returns {void}
96
+ */
97
+ export function setMemberId(memberId) {
98
+ global.qlitics("set", "member-id", memberId);
99
+ }
100
+
101
+ /**
102
+ * This event will register a social share of a story in qlitics
103
+ * @param {uuid} storyContentId The id of the story being shared
104
+ * @param {string} socialMediaType The social network the item is being shared on
105
+ * @param {string} storyUrl The canonical URL of the story
106
+ * @returns {void}
107
+ */
108
+ export function registerStoryShare(storyContentId, socialMediaType, storyUrl) {
109
+ global.qlitics("track", "story-share", {
110
+ "story-content-id": storyContentId,
111
+ "social-media-type": socialMediaType,
112
+ url: storyUrl,
113
+ });
114
+ }
package/client/start.js CHANGED
@@ -16,7 +16,7 @@ import { Provider } from "react-redux";
16
16
  import { IsomorphicComponent } from "../isomorphic/component";
17
17
  import { makePickComponentSync } from "../isomorphic/impl/make-pick-component-sync";
18
18
  import { createQtStore } from "../store/create-store";
19
- import { registerPageView } from "./analytics";
19
+ import { registerPageView, registerStoryShare, setMemberId, startAnalytics } from "./analytics";
20
20
  import { initializeFCM } from "./impl/fcm";
21
21
  import {
22
22
  checkForServiceWorkerUpdates,
@@ -40,9 +40,10 @@ export const app = {
40
40
  maybeNavigateTo,
41
41
  maybeSetUrl,
42
42
  registerPageView,
43
+ registerStoryShare,
44
+ setMemberId,
43
45
  };
44
46
 
45
-
46
47
  function getRouteDataAndPath(path, mountAt) {
47
48
  const relativePath = path.startsWith(mountAt) ? path.slice(mountAt.length) : path;
48
49
  return [`${mountAt || ""}/route-data.json`, relativePath];
@@ -247,7 +248,7 @@ function getJsonContent(id) {
247
248
  if (element) return JSON.parse(element.textContent);
248
249
  }
249
250
 
250
- const performance = window.performance || { mark: () => { }, measure: () => { } };
251
+ const performance = window.performance || { mark: () => {}, measure: () => {} };
251
252
  function runWithTiming(name, f) {
252
253
  performance.mark(`${name}Start`);
253
254
  f();
@@ -277,6 +278,9 @@ export function startApp(renderApplication, reducers, opts) {
277
278
  const dataPromise = staticData
278
279
  ? Promise.resolve(staticData.qt)
279
280
  : getRouteData(path, { existingFetch: global.initialFetch });
281
+
282
+ startAnalytics();
283
+
280
284
  const store = createQtStore(
281
285
  reducers,
282
286
  (staticData && staticData.qt) || global.initialPage || getJsonContent("initial-page") || {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quintype/framework",
3
- "version": "7.34.4-qlitics-removal.0",
3
+ "version": "7.34.4",
4
4
  "description": "Libraries to help build Quintype Node.js apps",
5
5
  "main": "index.js",
6
6
  "engines": {
@@ -33,7 +33,7 @@
33
33
  "@ampproject/toolbox-optimizer": "2.8.3",
34
34
  "@grpc/grpc-js": "^1.12.5",
35
35
  "@jsdoc/salty": "^0.2.9",
36
- "@quintype/amp": "^2.21.4",
36
+ "@quintype/amp": "^2.22.0",
37
37
  "@quintype/backend": "^2.7.0",
38
38
  "@quintype/components": "^3.5.0",
39
39
  "@quintype/prerender-node": "^3.2.26",
@@ -57,7 +57,10 @@ async function ampStoryPageHandler(
57
57
  const story = await Story.getStoryBySlug(client, req.params["0"]);
58
58
  const isAmpDisabled = get(story, ["metadata", "story-attributes", "disable-amp-for-single-story", "0"], "false");
59
59
 
60
- if (!isVisualStory && (!enableAmp || isAmpDisabled === "true")) {
60
+ const getDisableAmpUnit = get(opts, ["disableAmpUnit"], false);
61
+ const disableAmpUnit = typeof getDisableAmpUnit === "function" && opts.disableAmpUnit(story);
62
+
63
+ if (disableAmpUnit || (!isVisualStory && (!enableAmp || isAmpDisabled === "true"))) {
61
64
  const ampPageBasePath = getAmpPageBasePath(opts, config);
62
65
  const redirectUrl = `/${req.params[0]}`.startsWith(ampPageBasePath)
63
66
  ? `/${req.params[0]}`.replace(ampPageBasePath, "")
package/server/routes.js CHANGED
@@ -680,6 +680,27 @@ exports.mountQuintypeAt = function (app, mountAt) {
680
680
  * To disable amp version for a specific story, you need to create a story attribute in bold with the slug {disable-amp-for-single-story} and values {true} and {false}. Set its value to "true" in the story which you want to disable amp. Please make sure to name the attributes and values in the exact same way as mentioned
681
681
  * attribute slug: "disable-amp-for-single-story" values: "true" , "false". This will redirect '<amp-page-base-path>/:slug' to the non-amp page
682
682
  *
683
+ * To disable the AMP version for a specific story template or section, pass opts.disableAmpUnit as a function that always returns a boolean value. When the function returns true, AMP will be disabled for the specified scenario.
684
+ * Note: Ensure that disableAmpUnit is always a function and returns a boolean value, as demonstrated below.
685
+ *
686
+ * Under app/server/app.js
687
+ *
688
+ * ``` const getTemplate = (story) => {
689
+ * return story.["story-template"] === "template-name";
690
+ * };
691
+ *
692
+ * ....
693
+ *
694
+ * ampRoutes(app, {
695
+ * seo: generateSeo,
696
+ * disableAmpUnit: (story) => getTemplate(story),
697
+ * featureConfig: {
698
+ * .....
699
+ * }
700
+ * ...
701
+ * .....
702
+ * })```
703
+ *
683
704
  * @param {Express} app Express app to add the routes to
684
705
  * @param {Object} opts Options object used to configure amp. Passing this is optional
685
706
  * @param {Object} opts.templates An object that's used to pass custom templates. Each key corresponds to the template name and corresponding value is the template