@mindful-web/marko-web-native-x 1.0.0

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.
Files changed (51) hide show
  1. package/.eslintignore +1 -0
  2. package/LICENSE +21 -0
  3. package/README.md +243 -0
  4. package/apollo/create-client.js +42 -0
  5. package/apollo/graphql/fragments/image.js +12 -0
  6. package/apollo/graphql/fragments/publisher-stories.js +20 -0
  7. package/apollo/graphql/fragments/related-stories.js +20 -0
  8. package/apollo/graphql/fragments/story.js +24 -0
  9. package/apollo/graphql/queries/publisher-stories.js +19 -0
  10. package/apollo/graphql/queries/related-stories.js +19 -0
  11. package/apollo/graphql/queries/story.js +15 -0
  12. package/browser/.eslintrc.js +1 -0
  13. package/browser/index.js +10 -0
  14. package/browser/track-end-of-content.vue +20 -0
  15. package/browser/track-outbound-links.vue +26 -0
  16. package/browser/track-social-share.vue +23 -0
  17. package/components/fetch-elements.marko +21 -0
  18. package/components/fetch-elements.marko.js +58 -0
  19. package/components/gtm-init.marko +21 -0
  20. package/components/gtm-init.marko.js +60 -0
  21. package/components/init.marko +35 -0
  22. package/components/init.marko.js +63 -0
  23. package/components/marko.json +72 -0
  24. package/components/publisher-stories.marko +64 -0
  25. package/components/publisher-stories.marko.js +96 -0
  26. package/components/render.marko +33 -0
  27. package/components/render.marko.js +75 -0
  28. package/components/retrieve.marko +44 -0
  29. package/components/retrieve.marko.js +94 -0
  30. package/components/story/advertiser-related-stories.marko +51 -0
  31. package/components/story/advertiser-related-stories.marko.js +84 -0
  32. package/components/story/track-end-of-content.marko +1 -0
  33. package/components/story/track-end-of-content.marko.js +30 -0
  34. package/components/story/track-init.marko +13 -0
  35. package/components/story/track-init.marko.js +45 -0
  36. package/components/story/track-outbound-links.marko +3 -0
  37. package/components/story/track-outbound-links.marko.js +32 -0
  38. package/components/story/track-page-view.marko +1 -0
  39. package/components/story/track-page-view.marko.js +32 -0
  40. package/components/story/track-social-share.marko +1 -0
  41. package/components/story/track-social-share.marko.js +30 -0
  42. package/config.js +94 -0
  43. package/marko.json +6 -0
  44. package/middleware/with-story.js +35 -0
  45. package/package.json +32 -0
  46. package/services/fetch-elements.js +22 -0
  47. package/utils/convert-ad-to-content.js +39 -0
  48. package/utils/convert-ad-to-node.js +6 -0
  49. package/utils/convert-story-to-content.js +44 -0
  50. package/utils/create-headers.js +7 -0
  51. package/utils/gtm-events.js +20 -0
@@ -0,0 +1,51 @@
1
+ import defaultFragment from "../../apollo/graphql/fragments/related-stories";
2
+ import buildQuery from "../../apollo/graphql/queries/related-stories";
3
+
4
+ $ const { req, nativeX } = out.global;
5
+
6
+ $ const { advertiserId, externalId, publisherId, excludeStoryIds } = input;
7
+ $ const args = {
8
+ config: nativeX,
9
+ advertiserId,
10
+ externalId,
11
+ ...(publisherId && { publisherId }),
12
+ ...(excludeStoryIds && { excludeStoryIds }),
13
+ };
14
+
15
+ /**
16
+ * @param NativeXConfiguration The NativeX config
17
+ * @param object The Marko template to render
18
+ * @param Document A query fragment to be used with the story query
19
+ */
20
+ $ const getStories = async ({
21
+ config,
22
+ advertiserId,
23
+ externalId,
24
+ publisherId,
25
+ excludeStoryIds,
26
+ pagination,
27
+ queryFragment = defaultFragment,
28
+ } = {}) => {
29
+ const { data } = await config.client.query({
30
+ query: buildQuery(queryFragment),
31
+ variables: {
32
+ input: { advertiserId, externalId, publisherId, excludeStoryIds },
33
+ ...(pagination && { pagination }),
34
+ },
35
+ });
36
+
37
+ if (!data || !data.advertiserStories) return { nodes: [], pageInfo: {} };
38
+ const { pageInfo } = data.advertiserStories;
39
+ const nodes = data.advertiserStories.edges
40
+ .map(edge => (edge && edge.node ? edge.node : null))
41
+ .filter(c => c);
42
+ return { nodes, pageInfo };
43
+ };
44
+ <if(nativeX && (externalId|| advertiserId))>
45
+ <marko-web-resolve|{ resolved }| promise=getStories(args)>
46
+ <${input.renderBody} nodes=resolved.nodes pageInfo=resolved.pageInfo />
47
+ </marko-web-resolve>
48
+ </if>
49
+ <else>
50
+ $ warn('Unable to fetch elements from NativeX: a uri and advertiser ID are required.');
51
+ </else>
@@ -0,0 +1,84 @@
1
+ // Compiled using marko@4.20.2 - DO NOT EDIT
2
+ "use strict";
3
+
4
+ var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
+ marko_componentType = "/@mindful-web/marko-web-native-x$1.0.0/components/story/advertiser-related-stories.marko",
6
+ marko_component = require("./advertiser-related-stories.marko"),
7
+ marko_renderer = require("marko/dist/runtime/components/renderer"),
8
+ module_defaultFragment = require("../../apollo/graphql/fragments/related-stories"),
9
+ defaultFragment = module_defaultFragment.default || module_defaultFragment,
10
+ module_buildQuery = require("../../apollo/graphql/queries/related-stories"),
11
+ buildQuery = module_buildQuery.default || module_buildQuery,
12
+ marko_dynamicTag = require("marko/dist/runtime/helpers/dynamic-tag"),
13
+ marko_web_resolve_template = require("@mindful-web/marko-core/components/resolve.marko"),
14
+ marko_loadTag = require("marko/dist/runtime/helpers/load-tag"),
15
+ marko_web_resolve_tag = marko_loadTag(marko_web_resolve_template);
16
+
17
+ function render(input, out, __component, component, state) {
18
+ var data = input;
19
+
20
+ const { req, nativeX } = out.global;
21
+
22
+ const { advertiserId, externalId, publisherId, excludeStoryIds } = input;
23
+
24
+ const args = {
25
+ config: nativeX,
26
+ advertiserId,
27
+ externalId,
28
+ ...(publisherId && { publisherId }),
29
+ ...(excludeStoryIds && { excludeStoryIds }),
30
+ };
31
+
32
+ const getStories = async ({
33
+ config,
34
+ advertiserId,
35
+ externalId,
36
+ publisherId,
37
+ excludeStoryIds,
38
+ pagination,
39
+ queryFragment = defaultFragment,
40
+ } = {}) => {
41
+ const { data } = await config.client.query({
42
+ query: buildQuery(queryFragment),
43
+ variables: {
44
+ input: { advertiserId, externalId, publisherId, excludeStoryIds },
45
+ ...(pagination && { pagination }),
46
+ },
47
+ });
48
+
49
+ if (!data || !data.advertiserStories) return { nodes: [], pageInfo: {} };
50
+ const { pageInfo } = data.advertiserStories;
51
+ const nodes = data.advertiserStories.edges
52
+ .map(edge => (edge && edge.node ? edge.node : null))
53
+ .filter(c => c);
54
+ return { nodes, pageInfo };
55
+ };
56
+
57
+ if (nativeX && (externalId || advertiserId)) {
58
+ marko_web_resolve_tag({
59
+ promise: getStories(args),
60
+ renderBody: function(out, { resolved }) {
61
+ marko_dynamicTag(out, input.renderBody, function() {
62
+ return {
63
+ nodes: resolved.nodes,
64
+ pageInfo: resolved.pageInfo
65
+ };
66
+ }, null, null, null, __component, "1");
67
+ }
68
+ }, out, __component, "0");
69
+ } else {
70
+ warn('Unable to fetch elements from NativeX: a uri and advertiser ID are required.');
71
+ }
72
+ }
73
+
74
+ marko_template._ = marko_renderer(render, {
75
+ e_: marko_componentType
76
+ }, marko_component);
77
+
78
+ marko_template.meta = {
79
+ id: "/@mindful-web/marko-web-native-x$1.0.0/components/story/advertiser-related-stories.marko",
80
+ component: "./advertiser-related-stories.marko",
81
+ tags: [
82
+ "@mindful-web/marko-core/components/resolve.marko"
83
+ ]
84
+ };
@@ -0,0 +1 @@
1
+ <marko-web-browser-component name="NativeXTrackEndOfContent" props={} />
@@ -0,0 +1,30 @@
1
+ // Compiled using marko@4.20.2 - DO NOT EDIT
2
+ "use strict";
3
+
4
+ var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
+ marko_componentType = "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-end-of-content.marko",
6
+ marko_renderer = require("marko/dist/runtime/components/renderer"),
7
+ marko_web_browser_component_template = require("@mindful-web/marko-web/components/browser-component.marko"),
8
+ marko_loadTag = require("marko/dist/runtime/helpers/load-tag"),
9
+ marko_web_browser_component_tag = marko_loadTag(marko_web_browser_component_template);
10
+
11
+ function render(input, out, __component, component, state) {
12
+ var data = input;
13
+
14
+ marko_web_browser_component_tag({
15
+ name: "NativeXTrackEndOfContent",
16
+ props: {}
17
+ }, out, __component, "0");
18
+ }
19
+
20
+ marko_template._ = marko_renderer(render, {
21
+ d_: true,
22
+ e_: marko_componentType
23
+ });
24
+
25
+ marko_template.meta = {
26
+ id: "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-end-of-content.marko",
27
+ tags: [
28
+ "@mindful-web/marko-web/components/browser-component.marko"
29
+ ]
30
+ };
@@ -0,0 +1,13 @@
1
+ import { get, getAsObject } from "@mindful-web/object-path";
2
+
3
+ $ const { req } = out.global;
4
+ $ const story = getAsObject(input, "story");
5
+
6
+ <marko-web-gtm-push name="dataLayerNativeX" data={
7
+ story_id: story.id,
8
+ page_path: req.path,
9
+ page_title: story.title,
10
+ publisher_id: get(story, "publisher.id"),
11
+ advertiser_id: get(story, "advertiser.id"),
12
+ preview_mode: Boolean(req.query.preview),
13
+ } />
@@ -0,0 +1,45 @@
1
+ // Compiled using marko@4.20.2 - DO NOT EDIT
2
+ "use strict";
3
+
4
+ var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
+ marko_componentType = "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-init.marko",
6
+ marko_renderer = require("marko/dist/runtime/components/renderer"),
7
+ module_objectPath_module = require("@mindful-web/object-path"),
8
+ objectPath_module = module_objectPath_module.default || module_objectPath_module,
9
+ get = module_objectPath_module.get,
10
+ getAsObject = module_objectPath_module.getAsObject,
11
+ marko_web_gtm_push_template = require("@mindful-web/marko-web-gtm/components/push.marko"),
12
+ marko_loadTag = require("marko/dist/runtime/helpers/load-tag"),
13
+ marko_web_gtm_push_tag = marko_loadTag(marko_web_gtm_push_template);
14
+
15
+ function render(input, out, __component, component, state) {
16
+ var data = input;
17
+
18
+ const { req } = out.global;
19
+
20
+ const story = getAsObject(input, "story");
21
+
22
+ marko_web_gtm_push_tag({
23
+ name: "dataLayerNativeX",
24
+ data: {
25
+ story_id: story.id,
26
+ page_path: req.path,
27
+ page_title: story.title,
28
+ publisher_id: get(story, "publisher.id"),
29
+ advertiser_id: get(story, "advertiser.id"),
30
+ preview_mode: Boolean(req.query.preview)
31
+ }
32
+ }, out, __component, "0");
33
+ }
34
+
35
+ marko_template._ = marko_renderer(render, {
36
+ d_: true,
37
+ e_: marko_componentType
38
+ });
39
+
40
+ marko_template.meta = {
41
+ id: "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-init.marko",
42
+ tags: [
43
+ "@mindful-web/marko-web-gtm/components/push.marko"
44
+ ]
45
+ };
@@ -0,0 +1,3 @@
1
+ <marko-web-browser-component name="NativeXTrackOutboundLinks" props={
2
+ container: input.container,
3
+ } />
@@ -0,0 +1,32 @@
1
+ // Compiled using marko@4.20.2 - DO NOT EDIT
2
+ "use strict";
3
+
4
+ var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
+ marko_componentType = "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-outbound-links.marko",
6
+ marko_renderer = require("marko/dist/runtime/components/renderer"),
7
+ marko_web_browser_component_template = require("@mindful-web/marko-web/components/browser-component.marko"),
8
+ marko_loadTag = require("marko/dist/runtime/helpers/load-tag"),
9
+ marko_web_browser_component_tag = marko_loadTag(marko_web_browser_component_template);
10
+
11
+ function render(input, out, __component, component, state) {
12
+ var data = input;
13
+
14
+ marko_web_browser_component_tag({
15
+ name: "NativeXTrackOutboundLinks",
16
+ props: {
17
+ container: input.container
18
+ }
19
+ }, out, __component, "0");
20
+ }
21
+
22
+ marko_template._ = marko_renderer(render, {
23
+ d_: true,
24
+ e_: marko_componentType
25
+ });
26
+
27
+ marko_template.meta = {
28
+ id: "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-outbound-links.marko",
29
+ tags: [
30
+ "@mindful-web/marko-web/components/browser-component.marko"
31
+ ]
32
+ };
@@ -0,0 +1 @@
1
+ <marko-web-gtm-push name="dataLayerNativeX" data={ event: "page_load" } />
@@ -0,0 +1,32 @@
1
+ // Compiled using marko@4.20.2 - DO NOT EDIT
2
+ "use strict";
3
+
4
+ var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
+ marko_componentType = "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-page-view.marko",
6
+ marko_renderer = require("marko/dist/runtime/components/renderer"),
7
+ marko_web_gtm_push_template = require("@mindful-web/marko-web-gtm/components/push.marko"),
8
+ marko_loadTag = require("marko/dist/runtime/helpers/load-tag"),
9
+ marko_web_gtm_push_tag = marko_loadTag(marko_web_gtm_push_template);
10
+
11
+ function render(input, out, __component, component, state) {
12
+ var data = input;
13
+
14
+ marko_web_gtm_push_tag({
15
+ name: "dataLayerNativeX",
16
+ data: {
17
+ event: "page_load"
18
+ }
19
+ }, out, __component, "0");
20
+ }
21
+
22
+ marko_template._ = marko_renderer(render, {
23
+ d_: true,
24
+ e_: marko_componentType
25
+ });
26
+
27
+ marko_template.meta = {
28
+ id: "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-page-view.marko",
29
+ tags: [
30
+ "@mindful-web/marko-web-gtm/components/push.marko"
31
+ ]
32
+ };
@@ -0,0 +1 @@
1
+ <marko-web-browser-component name="NativeXTrackSocialShare" props={} />
@@ -0,0 +1,30 @@
1
+ // Compiled using marko@4.20.2 - DO NOT EDIT
2
+ "use strict";
3
+
4
+ var marko_template = module.exports = require("marko/dist/html").t(__filename),
5
+ marko_componentType = "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-social-share.marko",
6
+ marko_renderer = require("marko/dist/runtime/components/renderer"),
7
+ marko_web_browser_component_template = require("@mindful-web/marko-web/components/browser-component.marko"),
8
+ marko_loadTag = require("marko/dist/runtime/helpers/load-tag"),
9
+ marko_web_browser_component_tag = marko_loadTag(marko_web_browser_component_template);
10
+
11
+ function render(input, out, __component, component, state) {
12
+ var data = input;
13
+
14
+ marko_web_browser_component_tag({
15
+ name: "NativeXTrackSocialShare",
16
+ props: {}
17
+ }, out, __component, "0");
18
+ }
19
+
20
+ marko_template._ = marko_renderer(render, {
21
+ d_: true,
22
+ e_: marko_componentType
23
+ });
24
+
25
+ marko_template.meta = {
26
+ id: "/@mindful-web/marko-web-native-x$1.0.0/components/story/track-social-share.marko",
27
+ tags: [
28
+ "@mindful-web/marko-web/components/browser-component.marko"
29
+ ]
30
+ };
package/config.js ADDED
@@ -0,0 +1,94 @@
1
+ const { asArray } = require('@mindful-web/utils');
2
+ const { set, get, getAsObject } = require('@mindful-web/object-path');
3
+ const createClient = require('./apollo/create-client');
4
+
5
+ class NativeXConfiguration {
6
+ /**
7
+ *
8
+ * @param {string} uri
9
+ * @param {object} params
10
+ * @param {boolean} [params.enabled=true]
11
+ * @param {string} [params.defaultAlias=default]
12
+ */
13
+ constructor(uri, { enabled = true, defaultAlias = 'default', tenantKey } = {}) {
14
+ if (!uri) throw new Error('Unable to configure NativeX: no URI was provided.');
15
+ this.uri = uri;
16
+ this.enabled = enabled;
17
+ this.defaultAlias = defaultAlias;
18
+ this.tenantKey = tenantKey;
19
+
20
+ this.client = createClient(this.getGraphQLUri());
21
+ this.placements = {};
22
+ }
23
+
24
+ /**
25
+ *
26
+ * @param {object} params
27
+ * @param {string} params.alias The placement alias, e.g. `default` or `some-section-name`.
28
+ * @param {string} params.name The placement name, e.g. `primary` or `list1`, etc.
29
+ * @param {string} params.id The placement id, e.g. `5d4b04769f69b200013ab109`.
30
+ */
31
+ setPlacement({ alias, name, id } = {}) {
32
+ if (!name || !alias || !id) throw new Error('Unable to create NativeX placement: the name, alias, and ID are required');
33
+ const placement = { id };
34
+ set(this.placements, `${alias}.${name}`, placement);
35
+ return this;
36
+ }
37
+
38
+ /**
39
+ *
40
+ * @param {object} params
41
+ * @param {string} params.name The placement name, e.g. `primary` or `list1`, etc.
42
+ * @param {string[]} params.aliases The placement aliases to traverse when loading the placement.
43
+ */
44
+ getPlacement({ name, aliases } = {}) {
45
+ // Retrieve the default and "alias-traversed" placements.
46
+ const defaultPlacement = getAsObject(this.placements, `${this.defaultAlias}.${name}`);
47
+ const foundPlacement = asArray(aliases).map((alias) => get(this.placements, `${alias}.${name}`)).filter((v) => v)[0];
48
+
49
+ // Ensure placement is duplicated so property re-assignment doesn't "stick."
50
+ return {
51
+ ...getAsObject(foundPlacement || defaultPlacement),
52
+ enabled: this.enabled,
53
+ uri: this.uri,
54
+ };
55
+ }
56
+
57
+ /**
58
+ *
59
+ * @param {string} alias
60
+ * @param {object[]} definitions
61
+ */
62
+ setAliasPlacements(alias, definitions) {
63
+ asArray(definitions).forEach((definition) => {
64
+ this.setPlacement({ ...definition, alias });
65
+ });
66
+ return this;
67
+ }
68
+
69
+ getUri() {
70
+ return this.uri;
71
+ }
72
+
73
+ getGraphQLUri() {
74
+ return `${this.uri}/graph`;
75
+ }
76
+
77
+ isEnabled() {
78
+ return this.enabled;
79
+ }
80
+
81
+ getTenantKey() {
82
+ const { tenantKey } = this;
83
+ if (tenantKey) return tenantKey;
84
+ const [, key] = this.uri.match(/\/\/(\w+)\.native-x/i);
85
+ return key;
86
+ }
87
+
88
+ getEntityFor(type) {
89
+ const tenantKey = this.getTenantKey();
90
+ return `native-x.${tenantKey}.${type}`;
91
+ }
92
+ }
93
+
94
+ module.exports = NativeXConfiguration;
package/marko.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "taglib-id": "@mindful-web/marko-web-native-x",
3
+ "taglib-imports": [
4
+ "./components/marko.json"
5
+ ]
6
+ }
@@ -0,0 +1,35 @@
1
+ const { asyncRoute } = require('@mindful-web/utils');
2
+ const { getAsObject } = require('@mindful-web/object-path');
3
+ const defaultFragment = require('../apollo/graphql/fragments/story');
4
+ const buildQuery = require('../apollo/graphql/queries/story');
5
+
6
+ /**
7
+ * @param NativeXConfiguration The NativeX config
8
+ * @param object The Marko template to render
9
+ * @param Document A query fragment to be used with the story query
10
+ * @param object Headers to send with the API request
11
+ */
12
+ module.exports = ({
13
+ config,
14
+ template,
15
+ queryFragment = defaultFragment,
16
+ headers = {},
17
+ } = {}) => asyncRoute(async (req, res) => {
18
+ const { path, url } = req;
19
+ if (path.substr(-1) === '/' && path.length > 1) {
20
+ const query = url.slice(path.length);
21
+ const safe = path.slice(0, -1).replace(/\/+/g, '/');
22
+ res.redirect(301, `${safe}${query}`);
23
+ return;
24
+ }
25
+
26
+ const { id } = req.params;
27
+ const preview = Boolean(req.query.preview);
28
+ const result = await config.client.query({
29
+ query: buildQuery(queryFragment),
30
+ variables: { input: { id, preview } },
31
+ headers,
32
+ });
33
+ const story = getAsObject(result, 'data.publishedStory');
34
+ res.marko(template, { story });
35
+ });
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@mindful-web/marko-web-native-x",
3
+ "version": "1.0.0",
4
+ "description": "NativeX Marko components for Mindful Web websites",
5
+ "author": "Jacob Bare <jacob@parameter1.com>",
6
+ "license": "MIT",
7
+ "repository": "https://github.com/parameter1/mindful-web/tree/main/packages/marko-web-native-x",
8
+ "scripts": {
9
+ "lint:fix": "yarn lint --fix",
10
+ "lint": "eslint --ext .js --ext .vue --max-warnings 5 ./",
11
+ "compile": "mindful-web-marko-compile compile",
12
+ "prepublish": "yarn compile --silent",
13
+ "test": "yarn compile --no-clean && yarn lint"
14
+ },
15
+ "dependencies": {
16
+ "@mindful-web/marko-web-deferred-script-loader": "^1.0.0",
17
+ "@mindful-web/marko-web-gtm": "^1.0.0",
18
+ "@mindful-web/object-path": "^1.0.0",
19
+ "@mindful-web/utils": "^1.0.0",
20
+ "@mindful-web/web-common": "^1.0.0",
21
+ "graphql-tag": "^2.12.6",
22
+ "node-fetch": "^2.6.9"
23
+ },
24
+ "peerDependencies": {
25
+ "@mindful-web/marko-core": "^0.0.0",
26
+ "@mindful-web/marko-web": "^0.0.0"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "gitHead": "0b77cab713eb5841202bb86c7119949866bc68b5"
32
+ }
@@ -0,0 +1,22 @@
1
+ const { isObject } = require('@mindful-web/utils');
2
+ const fetch = require('node-fetch');
3
+ const createHeaders = require('../utils/create-headers');
4
+
5
+ module.exports = async ({
6
+ uri,
7
+ placementId,
8
+ opts,
9
+ req,
10
+ }) => {
11
+ const query = isObject(opts) ? `?opts=${encodeURIComponent(JSON.stringify(opts))}` : '';
12
+ const url = `${uri}/placement/elements/${placementId}.json${query}`;
13
+ const response = await fetch(url, { headers: createHeaders({ req }) });
14
+ const json = await response.json();
15
+ if (!response.ok) {
16
+ const err = new Error(response.statusMessage);
17
+ err.statusCode = response.statusText;
18
+ err.body = json;
19
+ throw err;
20
+ }
21
+ return json;
22
+ };
@@ -0,0 +1,39 @@
1
+ const { get } = require('@mindful-web/object-path');
2
+
3
+ module.exports = (ad = {}, { sectionName = 'Sponsored' } = {}) => {
4
+ const { campaign, creative, image } = ad;
5
+ const startDate = get(campaign, 'criteria.start');
6
+ const { updatedAt } = campaign;
7
+ return {
8
+ id: campaign.id,
9
+ name: creative.title,
10
+ shortName: creative.title,
11
+ typeTitled: 'Text Ad',
12
+ type: 'text-ad',
13
+ teaser: creative.teaser,
14
+ linkText: creative.linkText,
15
+ published: updatedAt > startDate ? updatedAt : startDate,
16
+ canonicalPath: ad.href, // @deprecated. Use siteContext.path instead
17
+ siteContext: {
18
+ path: ad.href,
19
+ canonicalUrl: ad.href,
20
+ __typename: 'ContentSiteContext',
21
+ },
22
+ primaryImage: {
23
+ id: image.id,
24
+ alt: creative.title,
25
+ src: image.src,
26
+ __typename: 'AssetImage',
27
+ },
28
+ primarySection: {
29
+ name: sectionName,
30
+ fullName: sectionName,
31
+ __typename: 'WebsiteSection',
32
+ },
33
+ company: {
34
+ name: campaign.advertiserName,
35
+ __typename: 'ContentCompany',
36
+ },
37
+ __typename: 'ContentTextAd',
38
+ };
39
+ };
@@ -0,0 +1,6 @@
1
+ const convertAdToContent = require('./convert-ad-to-content');
2
+
3
+ module.exports = (ad, { sectionName = 'Sponsored' } = {}) => {
4
+ const node = convertAdToContent(ad, { sectionName });
5
+ return { node, attrs: ad.attributes.container, linkAttrs: ad.attributes.link };
6
+ };
@@ -0,0 +1,44 @@
1
+ const { get, getAsObject } = require('@mindful-web/object-path');
2
+
3
+ module.exports = (story = {}, { sectionName = 'Sponsored' } = {}) => {
4
+ const advertiser = getAsObject(story, 'advertiser');
5
+ const contentImage = getAsObject(story, 'primaryImage');
6
+ const advertiserImage = getAsObject(story, 'advertiser.logo');
7
+ return {
8
+ id: story.id,
9
+ name: story.title,
10
+ shortName: story.title,
11
+ body: story.body,
12
+ typeTitled: 'Article',
13
+ type: 'article',
14
+ teaser: story.teaser,
15
+ published: get(story, 'publishedAt'),
16
+ siteContext: {
17
+ path: story.url,
18
+ canonicalUrl: story.url,
19
+ __typename: 'ContentSiteContext',
20
+ },
21
+ primaryImage: {
22
+ id: contentImage.id,
23
+ alt: story.title,
24
+ src: contentImage.src,
25
+ __typename: 'AssetImage',
26
+ },
27
+ primarySection: {
28
+ name: sectionName,
29
+ fullName: sectionName,
30
+ __typename: 'WebsiteSection',
31
+ },
32
+ company: {
33
+ name: advertiser.name,
34
+ primaryImage: {
35
+ id: advertiserImage.id,
36
+ alt: advertiser.name,
37
+ src: advertiserImage.src,
38
+ __typename: 'AssetImage',
39
+ },
40
+ __typename: 'ContentCompany',
41
+ },
42
+ __typename: 'ContentArticle',
43
+ };
44
+ };
@@ -0,0 +1,7 @@
1
+ module.exports = ({ req }) => {
2
+ if (!req) return {};
3
+ return {
4
+ 'x-forwarded-for': req.ip,
5
+ 'user-agent': req.get('user-agent'),
6
+ };
7
+ };
@@ -0,0 +1,20 @@
1
+ /* eslint-disable no-undef */
2
+ export const pageLoad = () => {
3
+ const dataLayer = window.dataLayerNativeX;
4
+ if (dataLayer) dataLayer.push({ event: 'page_load' });
5
+ };
6
+
7
+ export const outboundLink = (url) => {
8
+ const dataLayer = window.dataLayerNativeX;
9
+ if (dataLayer) dataLayer.push({ event: 'outbound_click', outbound_url: url, eventTimeout: 3000 });
10
+ };
11
+
12
+ export const share = (provider) => {
13
+ const dataLayer = window.dataLayerNativeX;
14
+ if (dataLayer) dataLayer.push({ event: 'share', social_provider: provider });
15
+ };
16
+
17
+ export const endOfContent = () => {
18
+ const dataLayer = window.dataLayerNativeX;
19
+ if (dataLayer) dataLayer.push({ event: 'scroll_to_bottom' });
20
+ };