@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.
- package/.eslintignore +1 -0
- package/LICENSE +21 -0
- package/README.md +243 -0
- package/apollo/create-client.js +42 -0
- package/apollo/graphql/fragments/image.js +12 -0
- package/apollo/graphql/fragments/publisher-stories.js +20 -0
- package/apollo/graphql/fragments/related-stories.js +20 -0
- package/apollo/graphql/fragments/story.js +24 -0
- package/apollo/graphql/queries/publisher-stories.js +19 -0
- package/apollo/graphql/queries/related-stories.js +19 -0
- package/apollo/graphql/queries/story.js +15 -0
- package/browser/.eslintrc.js +1 -0
- package/browser/index.js +10 -0
- package/browser/track-end-of-content.vue +20 -0
- package/browser/track-outbound-links.vue +26 -0
- package/browser/track-social-share.vue +23 -0
- package/components/fetch-elements.marko +21 -0
- package/components/fetch-elements.marko.js +58 -0
- package/components/gtm-init.marko +21 -0
- package/components/gtm-init.marko.js +60 -0
- package/components/init.marko +35 -0
- package/components/init.marko.js +63 -0
- package/components/marko.json +72 -0
- package/components/publisher-stories.marko +64 -0
- package/components/publisher-stories.marko.js +96 -0
- package/components/render.marko +33 -0
- package/components/render.marko.js +75 -0
- package/components/retrieve.marko +44 -0
- package/components/retrieve.marko.js +94 -0
- package/components/story/advertiser-related-stories.marko +51 -0
- package/components/story/advertiser-related-stories.marko.js +84 -0
- package/components/story/track-end-of-content.marko +1 -0
- package/components/story/track-end-of-content.marko.js +30 -0
- package/components/story/track-init.marko +13 -0
- package/components/story/track-init.marko.js +45 -0
- package/components/story/track-outbound-links.marko +3 -0
- package/components/story/track-outbound-links.marko.js +32 -0
- package/components/story/track-page-view.marko +1 -0
- package/components/story/track-page-view.marko.js +32 -0
- package/components/story/track-social-share.marko +1 -0
- package/components/story/track-social-share.marko.js +30 -0
- package/config.js +94 -0
- package/marko.json +6 -0
- package/middleware/with-story.js +35 -0
- package/package.json +32 -0
- package/services/fetch-elements.js +22 -0
- package/utils/convert-ad-to-content.js +39 -0
- package/utils/convert-ad-to-node.js +6 -0
- package/utils/convert-story-to-content.js +44 -0
- package/utils/create-headers.js +7 -0
- 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,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,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,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
|
+
};
|