@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 +2 -0
- package/client/analytics.js +99 -1
- package/client/start.js +7 -3
- package/package.json +2 -2
- package/server/amp/handlers/story-page.js +4 -1
- package/server/routes.js +21 -0
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
|
|
package/client/analytics.js
CHANGED
|
@@ -1,10 +1,84 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
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: () => {
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|