ghost 6.8.1 → 6.9.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/components/tryghost-i18n-6.9.0.tgz +0 -0
- package/core/built/admin/assets/activitypub/activitypub.js +2 -2
- package/core/built/admin/assets/activitypub/{index-BbINZU9U.mjs → index-B29oZuTp.mjs} +2 -2
- package/core/built/admin/assets/activitypub/{index-C3M839De.mjs → index-C19nEXqT.mjs} +7998 -7923
- package/core/built/admin/assets/admin-x-settings/{CodeEditorView-Dh1am4P6.mjs → CodeEditorView-BNKxdfRt.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
- package/core/built/admin/assets/admin-x-settings/{index-DqbTDHzA.mjs → index-B-_a183c.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-Hwd1HJ0-.mjs → index-CjRGpMVv.mjs} +2 -2
- package/core/built/admin/assets/admin-x-settings/{index-SxxA3jSX.mjs → index-Q0XmL0KU.mjs} +5 -5
- package/core/built/admin/assets/admin-x-settings/{modals-yhgQVHax.mjs → modals-omgXN6i-.mjs} +31 -27
- package/core/built/admin/assets/{chunk.524.bc2b771f38286b4a51ed.js → chunk.524.774a2df444e2ffde4942.js} +7 -7
- package/core/built/admin/assets/{chunk.582.a28f953895ae17fb3b24.js → chunk.582.ca4f05f3c39fda05b54c.js} +9 -9
- package/core/built/admin/assets/{ghost-7556359b8bd4ec08a6c23890b04bb56e.js → ghost-94d0fbb20e8e880fa9ba144cf26ab050.js} +27 -27
- package/core/built/admin/assets/ghost-dark-6c9cfa9c364e28c57e5983f68ec6f2fc.css +1 -0
- package/core/built/admin/assets/ghost-f724c1d53f5402f78a2d8cf8beb7c716.css +1 -0
- package/core/built/admin/assets/posts/posts.js +1 -1
- package/core/built/admin/assets/stats/stats.js +1 -1
- package/core/built/admin/index.html +4 -4
- package/core/frontend/public/robots.txt +1 -0
- package/core/frontend/web/middleware/index.js +0 -1
- package/core/frontend/web/routers/serve-favicon.js +56 -0
- package/core/frontend/web/site.js +2 -1
- package/core/server/data/tinybird/endpoints/api_kpis.pipe +0 -3
- package/core/server/data/tinybird/endpoints/api_top_locations.pipe +0 -3
- package/core/server/data/tinybird/endpoints/api_top_pages.pipe +0 -5
- package/core/server/data/tinybird/pipes/filtered_sessions.pipe +0 -3
- package/core/server/data/tinybird/scripts/analytics-generator.js +106 -2
- package/core/server/data/tinybird/tests/api_kpis.yaml +0 -36
- package/core/server/data/tinybird/tests/api_top_locations.yaml +2 -31
- package/core/server/data/tinybird/tests/api_top_pages.yaml +1 -30
- package/core/server/data/tinybird/tests/api_top_sources.yaml +2 -41
- package/core/server/data/tinybird/tests/api_top_utm_campaigns.yaml +3 -33
- package/core/server/data/tinybird/tests/api_top_utm_contents.yaml +3 -39
- package/core/server/data/tinybird/tests/api_top_utm_mediums.yaml +3 -34
- package/core/server/data/tinybird/tests/api_top_utm_sources.yaml +3 -43
- package/core/server/data/tinybird/tests/api_top_utm_terms.yaml +3 -36
- package/core/server/services/email-address/EmailAddressService.js +4 -1
- package/core/server/services/email-address/EmailAddressService.ts +5 -1
- package/core/server/services/email-analytics/EmailAnalyticsService.js +70 -16
- package/core/server/services/email-analytics/EmailAnalyticsServiceWrapper.js +6 -0
- package/core/server/services/email-analytics/jobs/update-member-email-analytics/index.js +4 -3
- package/core/server/services/email-analytics/lib/queries.js +84 -0
- package/core/server/services/email-service/EmailEventProcessor.js +113 -13
- package/core/server/services/email-service/EmailEventStorage.js +191 -26
- package/core/server/services/email-service/EmailRenderer.js +10 -3
- package/core/server/services/email-service/SendingService.js +1 -1
- package/core/server/services/lib/MailgunClient.js +2 -1
- package/core/server/services/member-welcome-emails/jobs/index.js +2 -2
- package/core/server/services/members/members-api/repositories/MemberRepository.js +2 -1
- package/core/server/services/tinybird/TinybirdService.js +0 -3
- package/core/server/web/admin/app.js +3 -1
- package/core/server/web/admin/controller.js +2 -1
- package/core/shared/config/defaults.json +2 -1
- package/core/shared/config/helpers.js +13 -0
- package/core/shared/url-utils.js +4 -2
- package/package.json +5 -5
- package/tsconfig.tsbuildinfo +1 -1
- package/yarn.lock +158 -105
- package/components/tryghost-i18n-6.8.1.tgz +0 -0
- package/core/built/admin/assets/ghost-ca67b9eb701b867ae2a2fdd76cebdc17.css +0 -1
- package/core/built/admin/assets/ghost-dark-a5c3c5101d50a0af1f7b828ee387846d.css +0 -1
- package/core/frontend/web/middleware/serve-favicon.js +0 -72
- package/core/server/data/tinybird/endpoints/api_top_browsers.pipe +0 -54
- package/core/server/data/tinybird/endpoints/api_top_devices.pipe +0 -53
- package/core/server/data/tinybird/endpoints/api_top_os.pipe +0 -53
- package/core/server/data/tinybird/tests/api_top_browsers.yaml +0 -98
- package/core/server/data/tinybird/tests/api_top_devices.yaml +0 -75
- package/core/server/data/tinybird/tests/api_top_os.yaml +0 -80
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<title>Ghost</title>
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%226.
|
|
9
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22cdnUrl%22%3A%22%22%2C%22editorUrl%22%3A%22%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%226.9%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%2C%22editorFilename%22%3A%22koenig-lexical.umd.js%22%2C%22editorHash%22%3A%2237bd1e3e4d%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%22a4b3b38319%22%2C%22activitypubFilename%22%3A%22activitypub.js%22%2C%22activitypubHash%22%3A%2238e5073e2a%22%2C%22postsFilename%22%3A%22posts.js%22%2C%22postsHash%22%3A%22460f25b871%22%2C%22statsFilename%22%3A%22stats.js%22%2C%22statsHash%22%3A%22c820ebd57d%22%2C%22activitypubRemoteConfigUrl%22%3A%22%2F.ghost%2Factivitypub%2Fstable%2Fclient-config%22%7D" />
|
|
10
10
|
|
|
11
11
|
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1, minimal-ui, viewport-fit=cover" />
|
|
12
12
|
<meta name="pinterest" content="nopin" />
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
</style>
|
|
29
29
|
|
|
30
30
|
<link integrity="" rel="stylesheet" href="assets/vendor-0ede59da8efb5e28fa929557f7ff7154.css">
|
|
31
|
-
<link integrity="" rel="stylesheet" href="assets/ghost-
|
|
31
|
+
<link integrity="" rel="stylesheet" href="assets/ghost-f724c1d53f5402f78a2d8cf8beb7c716.css" title="light">
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
</head>
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
|
|
50
50
|
<script src="assets/vendor-aed0068cf9b67d042dd23a6343545b7b.js"></script>
|
|
51
51
|
<script src="assets/chunk.397.a720333cfffc99c47e71.js"></script>
|
|
52
|
-
<script src="assets/chunk.524.
|
|
53
|
-
<script src="assets/ghost-
|
|
52
|
+
<script src="assets/chunk.524.774a2df444e2ffde4942.js"></script>
|
|
53
|
+
<script src="assets/ghost-94d0fbb20e8e880fa9ba144cf26ab050.js"></script>
|
|
54
54
|
</body>
|
|
55
55
|
</html>
|
|
@@ -4,7 +4,6 @@ module.exports = {
|
|
|
4
4
|
frontendCaching: require('./frontend-caching'),
|
|
5
5
|
handleImageSizes: require('./handle-image-sizes'),
|
|
6
6
|
redirectGhostToAdmin: require('./redirect-ghost-to-admin'),
|
|
7
|
-
serveFavicon: require('./serve-favicon'),
|
|
8
7
|
servePublicFile: require('./serve-public-file'),
|
|
9
8
|
staticTheme: require('./static-theme')
|
|
10
9
|
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const crypto = require('crypto');
|
|
4
|
+
const config = require('../../../shared/config');
|
|
5
|
+
const {blogIcon} = require('../../../server/lib/image');
|
|
6
|
+
const urlUtils = require('../../../shared/url-utils');
|
|
7
|
+
const settingsCache = require('../../../shared/settings-cache');
|
|
8
|
+
|
|
9
|
+
const buildContentResponse = (ext, buf) => {
|
|
10
|
+
return {
|
|
11
|
+
headers: {
|
|
12
|
+
'Content-Type': `image/${ext}`,
|
|
13
|
+
'Content-Length': buf.length,
|
|
14
|
+
ETag: `"${crypto.createHash('md5').update(buf, 'utf8').digest('hex')}"`,
|
|
15
|
+
'Cache-Control': `public, max-age=${config.get('caching:favicon:maxAge')}`
|
|
16
|
+
},
|
|
17
|
+
body: buf
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Handles requests to /favicon.ico, /favicon.png, /favicon.jpg, /favicon.jpeg
|
|
22
|
+
module.exports = function serveFavicon(siteApp) {
|
|
23
|
+
siteApp.get(/^\/favicon\.(ico|png|jpe?g)$/i, (req, res, next) => {
|
|
24
|
+
// CASE: favicon is default
|
|
25
|
+
// confusing: if you upload an icon, it's same logic as storing images
|
|
26
|
+
// we store as /content/images, because this is the url path images get requested via the browser
|
|
27
|
+
// we are using an express route to skip /content/images and the result is a image path
|
|
28
|
+
// based on config.getContentPath('images') + req.path
|
|
29
|
+
// in this case we don't use path rewrite, that's why we have to make it manually
|
|
30
|
+
const filePath = blogIcon.getIconPath();
|
|
31
|
+
const originalExtension = path.extname(filePath).toLowerCase();
|
|
32
|
+
const requestedExtension = path.extname(req.path).toLowerCase();
|
|
33
|
+
|
|
34
|
+
// CASE: custom favicon exists, load it from local file storage
|
|
35
|
+
if (settingsCache.get('icon')) {
|
|
36
|
+
// Always redirect to the icon path, which is never favicon.xxx
|
|
37
|
+
return res.redirect(302, blogIcon.getIconUrl());
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// CASE: always redirect to .ico for default icon
|
|
41
|
+
if (originalExtension !== requestedExtension) {
|
|
42
|
+
return res.redirect(302, urlUtils.urlFor({relativeUrl: '/favicon.ico'}));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fs.readFile(filePath, (err, buf) => {
|
|
46
|
+
if (err) {
|
|
47
|
+
return next(err);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const content = buildContentResponse('x-icon', buf);
|
|
51
|
+
|
|
52
|
+
res.writeHead(200, content.headers);
|
|
53
|
+
res.end(content.body);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
};
|
|
@@ -9,6 +9,7 @@ const config = require('../../shared/config');
|
|
|
9
9
|
const storage = require('../../server/adapters/storage');
|
|
10
10
|
const urlUtils = require('../../shared/url-utils');
|
|
11
11
|
const sitemapHandler = require('../services/sitemap/handler');
|
|
12
|
+
const serveFavicon = require('./routers/serve-favicon');
|
|
12
13
|
const themeEngine = require('../services/theme-engine');
|
|
13
14
|
const themeMiddleware = themeEngine.middleware;
|
|
14
15
|
const membersService = require('../../server/services/members');
|
|
@@ -62,7 +63,7 @@ module.exports = function setupSiteApp(routerConfig) {
|
|
|
62
63
|
// Static content/assets
|
|
63
64
|
// @TODO make sure all of these have a local 404 error handler
|
|
64
65
|
// Favicon
|
|
65
|
-
|
|
66
|
+
serveFavicon(siteApp);
|
|
66
67
|
|
|
67
68
|
// Serve sitemap.xsl file
|
|
68
69
|
siteApp.use(mw.servePublicFile('static', 'sitemap.xsl', 'text/xsl', config.get('caching:sitemapXSL:maxAge')));
|
|
@@ -140,9 +140,6 @@ SQL >
|
|
|
140
140
|
{% if defined(date_to) %} and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= {{ Date(date_to) }} {% else %} and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= today() {% end %}
|
|
141
141
|
{% end %}
|
|
142
142
|
{% if defined(member_status) %} and member_status IN {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }} {% end %}
|
|
143
|
-
{% if defined(device) %} and device = {{ String(device, description="Device to filter on", required=False) }} {% end %}
|
|
144
|
-
{% if defined(browser) %} and browser = {{ String(browser, description="Browser to filter on", required=False) }} {% end %}
|
|
145
|
-
{% if defined(os) %} and os = {{ String(os, description="Operating system to filter on", required=False) }} {% end %}
|
|
146
143
|
{% if defined(source) %} and source = {{ String(source, description="Source to filter on", required=False) }} {% end %}
|
|
147
144
|
{% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
|
|
148
145
|
{% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
|
|
@@ -39,9 +39,6 @@ SQL >
|
|
|
39
39
|
)
|
|
40
40
|
)
|
|
41
41
|
{% end %}
|
|
42
|
-
{% if defined(device) %} and device = {{ String(device, description="Device to filter on", required=False) }} {% end %}
|
|
43
|
-
{% if defined(browser) %} and browser = {{ String(browser, description="Browser to filter on", required=False) }} {% end %}
|
|
44
|
-
{% if defined(os) %} and os = {{ String(os, description="Operating system to filter on", required=False) }} {% end %}
|
|
45
42
|
{% if defined(source) %} and source = {{ String(source, description="Source to filter on", required=False) }} {% end %}
|
|
46
43
|
{% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
|
|
47
44
|
{% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
|
|
@@ -40,11 +40,6 @@ SQL >
|
|
|
40
40
|
)
|
|
41
41
|
)
|
|
42
42
|
{% end %}
|
|
43
|
-
{% if defined(device) %} and device = {{ String(device, description="Device to filter on", required=False) }} {% end %}
|
|
44
|
-
{% if defined(browser) %} and browser = {{ String(browser, description="Browser to filter on", required=False) }} {% end %}
|
|
45
|
-
{% if defined(os) %} and os = {{ String(os, description="Operating system to filter on", required=False) }} {% end %}
|
|
46
|
-
-- we do filtering on source in the filtered_sessions pipe
|
|
47
|
-
# --{% if defined(source) %} and source = {{ String(source, description="Source to filter on", required=False) }} {% end %}
|
|
48
43
|
{% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
|
|
49
44
|
{% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
|
|
50
45
|
{% if defined(post_uuid) %} and post_uuid = {{ String(post_uuid, description="Post UUID to filter on", required=False) }} {% end %}
|
|
@@ -20,9 +20,6 @@ SQL >
|
|
|
20
20
|
)
|
|
21
21
|
)
|
|
22
22
|
{% end %}
|
|
23
|
-
{% if defined(device) %} and device = {{ String(device, description="Device to filter on", required=False) }} {% end %}
|
|
24
|
-
{% if defined(browser) %} and browser = {{ String(browser, description="Browser to filter on", required=False) }} {% end %}
|
|
25
|
-
{% if defined(os) %} and os = {{ String(os, description="Operating system to filter on", required=False) }} {% end %}
|
|
26
23
|
{% if defined(source) %} and source = {{ String(source, description="Source to filter on", required=False) }} {% end %}
|
|
27
24
|
{% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
|
|
28
25
|
{% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
|
|
@@ -111,6 +111,59 @@ class AnalyticsEventGenerator {
|
|
|
111
111
|
this.locales = [
|
|
112
112
|
'en-US', 'en-GB', 'es-ES', 'fr-FR', 'de-DE', 'it-IT', 'pt-BR', 'ja-JP', 'ko-KR', 'zh-CN'
|
|
113
113
|
];
|
|
114
|
+
|
|
115
|
+
// UTM parameters for realistic campaign tracking
|
|
116
|
+
this.utmSources = [
|
|
117
|
+
{value: 'google', weight: 25},
|
|
118
|
+
{value: 'facebook', weight: 15},
|
|
119
|
+
{value: 'twitter', weight: 12},
|
|
120
|
+
{value: 'linkedin', weight: 10},
|
|
121
|
+
{value: 'reddit', weight: 8},
|
|
122
|
+
{value: 'newsletter', weight: 15},
|
|
123
|
+
{value: 'email', weight: 10},
|
|
124
|
+
{value: 'bluesky', weight: 5}
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
this.utmMediums = [
|
|
128
|
+
{value: 'cpc', weight: 30}, // Paid search
|
|
129
|
+
{value: 'social', weight: 25}, // Social media
|
|
130
|
+
{value: 'email', weight: 20}, // Email campaigns
|
|
131
|
+
{value: 'organic', weight: 15}, // Organic search
|
|
132
|
+
{value: 'referral', weight: 10} // Referral traffic
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
this.utmCampaigns = [
|
|
136
|
+
{value: 'spring_sale_2024', weight: 15},
|
|
137
|
+
{value: 'product_launch', weight: 12},
|
|
138
|
+
{value: 'weekly_newsletter', weight: 20},
|
|
139
|
+
{value: 'summer_promotion', weight: 10},
|
|
140
|
+
{value: 'black_friday', weight: 8},
|
|
141
|
+
{value: 'holiday_special', weight: 8},
|
|
142
|
+
{value: 'retargeting', weight: 12},
|
|
143
|
+
{value: 'brand_awareness', weight: 10},
|
|
144
|
+
{value: 'lead_generation', weight: 5}
|
|
145
|
+
];
|
|
146
|
+
|
|
147
|
+
this.utmContents = [
|
|
148
|
+
{value: 'header_cta', weight: 20},
|
|
149
|
+
{value: 'sidebar_banner', weight: 15},
|
|
150
|
+
{value: 'footer_link', weight: 10},
|
|
151
|
+
{value: 'inline_text', weight: 15},
|
|
152
|
+
{value: 'hero_button', weight: 20},
|
|
153
|
+
{value: 'popup_form', weight: 10},
|
|
154
|
+
{value: 'video_thumbnail', weight: 10}
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
this.utmTerms = [
|
|
158
|
+
{value: 'ghost_cms', weight: 15},
|
|
159
|
+
{value: 'blogging_platform', weight: 12},
|
|
160
|
+
{value: 'content_management', weight: 10},
|
|
161
|
+
{value: 'publishing_software', weight: 8},
|
|
162
|
+
{value: 'newsletter_tool', weight: 10},
|
|
163
|
+
{value: 'membership_site', weight: 8},
|
|
164
|
+
{value: 'headless_cms', weight: 7},
|
|
165
|
+
{value: 'open_source_blog', weight: 5}
|
|
166
|
+
];
|
|
114
167
|
|
|
115
168
|
// Weighted distributions based on production data
|
|
116
169
|
this.memberStatusWeights = [
|
|
@@ -497,6 +550,39 @@ class AnalyticsEventGenerator {
|
|
|
497
550
|
randomChoice(array) {
|
|
498
551
|
return array[Math.floor(Math.random() * array.length)];
|
|
499
552
|
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Generate UTM parameters for an event
|
|
556
|
+
* Returns null for ~50% of events (organic/direct traffic without UTM)
|
|
557
|
+
*/
|
|
558
|
+
generateUtmParameters() {
|
|
559
|
+
// 50% of events have no UTM parameters (organic/direct traffic)
|
|
560
|
+
if (Math.random() < 0.5) {
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
const utmParams = {
|
|
565
|
+
utm_source: this.weightedChoice(this.utmSources),
|
|
566
|
+
utm_medium: this.weightedChoice(this.utmMediums)
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
// 80% of UTM events include a campaign
|
|
570
|
+
if (Math.random() < 0.8) {
|
|
571
|
+
utmParams.utm_campaign = this.weightedChoice(this.utmCampaigns);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// 40% of UTM events include content
|
|
575
|
+
if (Math.random() < 0.4) {
|
|
576
|
+
utmParams.utm_content = this.weightedChoice(this.utmContents);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// 30% of UTM events include term (mainly for paid search)
|
|
580
|
+
if (Math.random() < 0.3 && utmParams.utm_medium === 'cpc') {
|
|
581
|
+
utmParams.utm_term = this.weightedChoice(this.utmTerms);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return utmParams;
|
|
585
|
+
}
|
|
500
586
|
|
|
501
587
|
/**
|
|
502
588
|
* Format timestamp to match the schema format
|
|
@@ -533,7 +619,19 @@ class AnalyticsEventGenerator {
|
|
|
533
619
|
|
|
534
620
|
// Generate referrerSource for meta field
|
|
535
621
|
const referrerSource = this.referrerSourceMap[referrer] || referrer;
|
|
536
|
-
|
|
622
|
+
|
|
623
|
+
// Generate UTM parameters
|
|
624
|
+
const utmParams = this.generateUtmParameters();
|
|
625
|
+
|
|
626
|
+
// Build href with UTM parameters if present
|
|
627
|
+
let href = `${this.baseUrl}${content.pathname}`;
|
|
628
|
+
if (utmParams) {
|
|
629
|
+
const utmQueryString = Object.entries(utmParams)
|
|
630
|
+
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
|
|
631
|
+
.join('&');
|
|
632
|
+
href = `${href}?${utmQueryString}`;
|
|
633
|
+
}
|
|
634
|
+
|
|
537
635
|
const payload = {
|
|
538
636
|
site_uuid: this.siteUuid,
|
|
539
637
|
member_uuid: memberUuid,
|
|
@@ -545,11 +643,16 @@ class AnalyticsEventGenerator {
|
|
|
545
643
|
location: this.weightedChoice(this.locationWeights),
|
|
546
644
|
referrer: referrer,
|
|
547
645
|
pathname: content.pathname,
|
|
548
|
-
href:
|
|
646
|
+
href: href,
|
|
549
647
|
meta: {
|
|
550
648
|
referrerSource: referrerSource
|
|
551
649
|
}
|
|
552
650
|
};
|
|
651
|
+
|
|
652
|
+
// Add UTM parameters to payload if present
|
|
653
|
+
if (utmParams) {
|
|
654
|
+
Object.assign(payload, utmParams);
|
|
655
|
+
}
|
|
553
656
|
|
|
554
657
|
return {
|
|
555
658
|
timestamp: this.formatTimestamp(timestamp),
|
|
@@ -591,6 +694,7 @@ class AnalyticsEventGenerator {
|
|
|
591
694
|
console.log(`📈 Traffic pattern: Moderate growth over time with realistic seasonal patterns`);
|
|
592
695
|
console.log(`⏰ Includes realistic daily/weekly patterns (weekdays > weekends, business hours > nights)`);
|
|
593
696
|
console.log(`🔗 Using production-based referrer patterns (Google, Reddit, Bluesky, newsletters, etc.)`);
|
|
697
|
+
console.log(`🎯 ~50% of events include UTM tracking parameters (source, medium, campaign, content, term)`);
|
|
594
698
|
|
|
595
699
|
for (let i = 0; i < numEvents; i++) {
|
|
596
700
|
events.push(this.generateEvent(i, numEvents));
|
|
@@ -11,30 +11,6 @@
|
|
|
11
11
|
{"date":"2100-01-06","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
|
|
12
12
|
{"date":"2100-01-07","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
|
|
13
13
|
|
|
14
|
-
- name: Filtered by browser - Chrome
|
|
15
|
-
description: Filtered by browser - Chrome
|
|
16
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&browser=chrome
|
|
17
|
-
expected_result: |
|
|
18
|
-
{"date":"2100-01-01","visits":1,"pageviews":2,"bounce_rate":0,"avg_session_sec":1111}
|
|
19
|
-
{"date":"2100-01-02","visits":0,"pageviews":0,"bounce_rate":0,"avg_session_sec":0}
|
|
20
|
-
{"date":"2100-01-03","visits":1,"pageviews":3,"bounce_rate":0,"avg_session_sec":1115}
|
|
21
|
-
{"date":"2100-01-04","visits":3,"pageviews":7,"bounce_rate":0.33,"avg_session_sec":572}
|
|
22
|
-
{"date":"2100-01-05","visits":1,"pageviews":3,"bounce_rate":0,"avg_session_sec":493}
|
|
23
|
-
{"date":"2100-01-06","visits":1,"pageviews":1,"bounce_rate":1,"avg_session_sec":0}
|
|
24
|
-
{"date":"2100-01-07","visits":0,"pageviews":0,"bounce_rate":0,"avg_session_sec":0}
|
|
25
|
-
|
|
26
|
-
- name: Filtered by device - desktop
|
|
27
|
-
description: Filtered by device - desktop
|
|
28
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&device=desktop
|
|
29
|
-
expected_result: |
|
|
30
|
-
{"date":"2100-01-01","visits":2,"pageviews":4,"bounce_rate":0,"avg_session_sec":870.5}
|
|
31
|
-
{"date":"2100-01-02","visits":1,"pageviews":3,"bounce_rate":0,"avg_session_sec":1027}
|
|
32
|
-
{"date":"2100-01-03","visits":3,"pageviews":7,"bounce_rate":0,"avg_session_sec":3333}
|
|
33
|
-
{"date":"2100-01-04","visits":3,"pageviews":7,"bounce_rate":0.33,"avg_session_sec":572}
|
|
34
|
-
{"date":"2100-01-05","visits":2,"pageviews":5,"bounce_rate":0,"avg_session_sec":308}
|
|
35
|
-
{"date":"2100-01-06","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
|
|
36
|
-
{"date":"2100-01-07","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
|
|
37
|
-
|
|
38
14
|
- name: Filtered by location - UK
|
|
39
15
|
description: Filtered by location - UK
|
|
40
16
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&location=GB
|
|
@@ -47,18 +23,6 @@
|
|
|
47
23
|
{"date":"2100-01-06","visits":1,"pageviews":1,"bounce_rate":1,"avg_session_sec":0}
|
|
48
24
|
{"date":"2100-01-07","visits":0,"pageviews":0,"bounce_rate":0,"avg_session_sec":0}
|
|
49
25
|
|
|
50
|
-
- name: Filtered by OS - Windows
|
|
51
|
-
description: Filtered by OS - Windows
|
|
52
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&os=windows
|
|
53
|
-
expected_result: |
|
|
54
|
-
{"date":"2100-01-01","visits":2,"pageviews":4,"bounce_rate":0,"avg_session_sec":870.5}
|
|
55
|
-
{"date":"2100-01-02","visits":1,"pageviews":3,"bounce_rate":0,"avg_session_sec":1027}
|
|
56
|
-
{"date":"2100-01-03","visits":3,"pageviews":7,"bounce_rate":0,"avg_session_sec":3333}
|
|
57
|
-
{"date":"2100-01-04","visits":3,"pageviews":7,"bounce_rate":0.33,"avg_session_sec":572}
|
|
58
|
-
{"date":"2100-01-05","visits":2,"pageviews":5,"bounce_rate":0,"avg_session_sec":308}
|
|
59
|
-
{"date":"2100-01-06","visits":1,"pageviews":1,"bounce_rate":1,"avg_session_sec":0}
|
|
60
|
-
{"date":"2100-01-07","visits":2,"pageviews":2,"bounce_rate":1,"avg_session_sec":0}
|
|
61
|
-
|
|
62
26
|
- name: Filtered by pathname - /about/
|
|
63
27
|
description: Filtered by pathname - /about/
|
|
64
28
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&pathname=%2Fabout%2F
|
|
@@ -9,40 +9,12 @@
|
|
|
9
9
|
{"location":"ES","visits":2}
|
|
10
10
|
{"location":"DE","visits":1}
|
|
11
11
|
|
|
12
|
-
- name: Filtered by browser - Chrome
|
|
13
|
-
description: Filtered by browser - Chrome
|
|
14
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&browser=chrome
|
|
15
|
-
expected_result: |
|
|
16
|
-
{"location":"GB","visits":5}
|
|
17
|
-
{"location":"DE","visits":1}
|
|
18
|
-
{"location":"ES","visits":1}
|
|
19
|
-
|
|
20
|
-
- name: Filtered by device - desktop
|
|
21
|
-
description: Filtered by device - desktop
|
|
22
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&device=desktop
|
|
23
|
-
expected_result: |
|
|
24
|
-
{"location":"GB","visits":7}
|
|
25
|
-
{"location":"US","visits":3}
|
|
26
|
-
{"location":"FR","visits":2}
|
|
27
|
-
{"location":"ES","visits":2}
|
|
28
|
-
{"location":"DE","visits":1}
|
|
29
|
-
|
|
30
12
|
- name: Filtered by location - UK
|
|
31
13
|
description: Filtered by location - UK
|
|
32
14
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&location=GB
|
|
33
15
|
expected_result: |
|
|
34
16
|
{"location":"GB","visits":8}
|
|
35
17
|
|
|
36
|
-
- name: Filtered by OS - Windows
|
|
37
|
-
description: Filtered by OS - Windows
|
|
38
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&os=windows
|
|
39
|
-
expected_result: |
|
|
40
|
-
{"location":"GB","visits":7}
|
|
41
|
-
{"location":"US","visits":3}
|
|
42
|
-
{"location":"ES","visits":2}
|
|
43
|
-
{"location":"FR","visits":1}
|
|
44
|
-
{"location":"DE","visits":1}
|
|
45
|
-
|
|
46
18
|
- name: Filtered by pathname - /about/
|
|
47
19
|
description: Filtered by pathname - /about/
|
|
48
20
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&pathname=%2Fabout%2F
|
|
@@ -98,8 +70,7 @@
|
|
|
98
70
|
|
|
99
71
|
- name: Test with multiple filters combined
|
|
100
72
|
description: Test with multiple filters combined
|
|
101
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&
|
|
73
|
+
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&source=bing.com&pathname=%2Fabout%2F
|
|
102
74
|
expected_result: |
|
|
103
|
-
{"location":"
|
|
104
|
-
{"location":"FR","visits":1}
|
|
75
|
+
{"location":"DE","visits":1}
|
|
105
76
|
{"location":"GB","visits":1}
|
|
@@ -8,23 +8,6 @@
|
|
|
8
8
|
{"post_uuid":"","pathname":"\/","visits":7}
|
|
9
9
|
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1dd","pathname":"\/blog\/hello-world\/","visits":1}
|
|
10
10
|
|
|
11
|
-
- name: Filtered by browser - Chrome
|
|
12
|
-
description: Filtered by browser - Chrome
|
|
13
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&browser=chrome
|
|
14
|
-
expected_result: |
|
|
15
|
-
{"post_uuid":"6b8635fb-292f-4422-9fe4-d76cfab2ba31","pathname":"\/blog\/hello-world\/","visits":6}
|
|
16
|
-
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1fc","pathname":"\/about\/","visits":3}
|
|
17
|
-
{"post_uuid":"","pathname":"\/","visits":3}
|
|
18
|
-
|
|
19
|
-
- name: Filtered by device - desktop
|
|
20
|
-
description: Filtered by device - desktop
|
|
21
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&device=desktop
|
|
22
|
-
expected_result: |
|
|
23
|
-
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1fc","pathname":"\/about\/","visits":8}
|
|
24
|
-
{"post_uuid":"6b8635fb-292f-4422-9fe4-d76cfab2ba31","pathname":"\/blog\/hello-world\/","visits":8}
|
|
25
|
-
{"post_uuid":"","pathname":"\/","visits":7}
|
|
26
|
-
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1dd","pathname":"\/blog\/hello-world\/","visits":1}
|
|
27
|
-
|
|
28
11
|
- name: Filtered by location - UK
|
|
29
12
|
description: Filtered by location - UK
|
|
30
13
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&location=GB
|
|
@@ -33,15 +16,6 @@
|
|
|
33
16
|
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1fc","pathname":"\/about\/","visits":4}
|
|
34
17
|
{"post_uuid":"","pathname":"\/","visits":4}
|
|
35
18
|
|
|
36
|
-
- name: Filtered by OS - Windows
|
|
37
|
-
description: Filtered by OS - Windows
|
|
38
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&os=windows
|
|
39
|
-
expected_result: |
|
|
40
|
-
{"post_uuid":"6b8635fb-292f-4422-9fe4-d76cfab2ba31","pathname":"\/blog\/hello-world\/","visits":8}
|
|
41
|
-
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1fc","pathname":"\/about\/","visits":7}
|
|
42
|
-
{"post_uuid":"","pathname":"\/","visits":7}
|
|
43
|
-
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1dd","pathname":"\/blog\/hello-world\/","visits":1}
|
|
44
|
-
|
|
45
19
|
- name: Filtered by pathname - /about/
|
|
46
20
|
description: Filtered by pathname - /about/
|
|
47
21
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&pathname=%2Fabout%2F
|
|
@@ -90,12 +64,9 @@
|
|
|
90
64
|
|
|
91
65
|
- name: Test with multiple filters combined
|
|
92
66
|
description: Test with multiple filters combined
|
|
93
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&
|
|
67
|
+
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&source=bing.com&pathname=%2Fabout%2F
|
|
94
68
|
expected_result: |
|
|
95
|
-
{"post_uuid":"","pathname":"\/","visits":3}
|
|
96
69
|
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1fc","pathname":"\/about\/","visits":2}
|
|
97
|
-
{"post_uuid":"6b8635fb-292f-4422-9fe4-d76cfab2ba31","pathname":"\/blog\/hello-world\/","visits":1}
|
|
98
|
-
{"post_uuid":"06b1b0c9-fb53-4a15-a060-3db3fde7b1dd","pathname":"\/blog\/hello-world\/","visits":1}
|
|
99
70
|
|
|
100
71
|
- name: Test with post_type - post
|
|
101
72
|
description: Test with post_type - post
|
|
@@ -13,28 +13,6 @@
|
|
|
13
13
|
{"source":"petty-queen.com","visits":1}
|
|
14
14
|
{"source":"my-ghost-site.com","visits":1}
|
|
15
15
|
|
|
16
|
-
- name: Filtered by browser - Chrome
|
|
17
|
-
description: Filtered by browser - Chrome
|
|
18
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&browser=chrome
|
|
19
|
-
expected_result: |
|
|
20
|
-
{"source":"","visits":4}
|
|
21
|
-
{"source":"bing.com","visits":1}
|
|
22
|
-
{"source":"search.yahoo.com","visits":1}
|
|
23
|
-
{"source":"baidu.com","visits":1}
|
|
24
|
-
|
|
25
|
-
- name: Filtered by device - desktop
|
|
26
|
-
description: Filtered by device - desktop
|
|
27
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&device=desktop
|
|
28
|
-
expected_result: |
|
|
29
|
-
{"source":"","visits":6}
|
|
30
|
-
{"source":"bing.com","visits":2}
|
|
31
|
-
{"source":"search.yahoo.com","visits":2}
|
|
32
|
-
{"source":"google.com","visits":1}
|
|
33
|
-
{"source":"baidu.com","visits":1}
|
|
34
|
-
{"source":"wilted-tick.com","visits":1}
|
|
35
|
-
{"source":"duckduckgo.com","visits":1}
|
|
36
|
-
{"source":"my-ghost-site.com","visits":1}
|
|
37
|
-
|
|
38
16
|
- name: Filtered by location - UK
|
|
39
17
|
description: Filtered by location - UK
|
|
40
18
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&location=GB
|
|
@@ -46,19 +24,6 @@
|
|
|
46
24
|
{"source":"baidu.com","visits":1}
|
|
47
25
|
{"source":"petty-queen.com","visits":1}
|
|
48
26
|
|
|
49
|
-
- name: Filtered by OS - Windows
|
|
50
|
-
description: Filtered by OS - Windows
|
|
51
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&os=windows
|
|
52
|
-
expected_result: |
|
|
53
|
-
{"source":"","visits":5}
|
|
54
|
-
{"source":"bing.com","visits":2}
|
|
55
|
-
{"source":"search.yahoo.com","visits":2}
|
|
56
|
-
{"source":"google.com","visits":1}
|
|
57
|
-
{"source":"baidu.com","visits":1}
|
|
58
|
-
{"source":"wilted-tick.com","visits":1}
|
|
59
|
-
{"source":"duckduckgo.com","visits":1}
|
|
60
|
-
{"source":"my-ghost-site.com","visits":1}
|
|
61
|
-
|
|
62
27
|
- name: Filtered by pathname - /about/
|
|
63
28
|
description: Filtered by pathname - /about/
|
|
64
29
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&pathname=%2Fabout%2F
|
|
@@ -118,13 +83,9 @@
|
|
|
118
83
|
|
|
119
84
|
- name: Test with multiple filters combined
|
|
120
85
|
description: Test with multiple filters combined
|
|
121
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&
|
|
86
|
+
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&source=bing.com&pathname=%2Fabout%2F
|
|
122
87
|
expected_result: |
|
|
123
|
-
{"source":"
|
|
124
|
-
{"source":"search.yahoo.com","visits":1}
|
|
125
|
-
{"source":"wilted-tick.com","visits":1}
|
|
126
|
-
{"source":"duckduckgo.com","visits":1}
|
|
127
|
-
{"source":"my-ghost-site.com","visits":1}
|
|
88
|
+
{"source":"bing.com","visits":2}
|
|
128
89
|
|
|
129
90
|
- name: Filtered by utm_source - google
|
|
130
91
|
description: Filtered by utm_source - google
|
|
@@ -10,25 +10,6 @@
|
|
|
10
10
|
{"utm_campaign":"retention_q4","visits":1}
|
|
11
11
|
{"utm_campaign":"newsletter_weekly","visits":1}
|
|
12
12
|
|
|
13
|
-
- name: Filtered by browser - Chrome
|
|
14
|
-
description: Filtered by browser - Chrome
|
|
15
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&browser=chrome
|
|
16
|
-
expected_result: |
|
|
17
|
-
{"utm_campaign":"brand_awareness","visits":2}
|
|
18
|
-
{"utm_campaign":"summer_sale_2024","visits":1}
|
|
19
|
-
{"utm_campaign":"retention_q4","visits":1}
|
|
20
|
-
|
|
21
|
-
- name: Filtered by device - desktop
|
|
22
|
-
description: Filtered by device - desktop
|
|
23
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&device=desktop
|
|
24
|
-
expected_result: |
|
|
25
|
-
{"utm_campaign":"brand_awareness","visits":2}
|
|
26
|
-
{"utm_campaign":"holiday_promo","visits":2}
|
|
27
|
-
{"utm_campaign":"product_launch","visits":2}
|
|
28
|
-
{"utm_campaign":"summer_sale_2024","visits":1}
|
|
29
|
-
{"utm_campaign":"retention_q4","visits":1}
|
|
30
|
-
{"utm_campaign":"newsletter_weekly","visits":1}
|
|
31
|
-
|
|
32
13
|
- name: Filtered by location - UK
|
|
33
14
|
description: Filtered by location - UK
|
|
34
15
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&location=GB
|
|
@@ -38,17 +19,6 @@
|
|
|
38
19
|
{"utm_campaign":"product_launch","visits":1}
|
|
39
20
|
{"utm_campaign":"newsletter_weekly","visits":1}
|
|
40
21
|
|
|
41
|
-
- name: Filtered by OS - Windows
|
|
42
|
-
description: Filtered by OS - Windows
|
|
43
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&os=windows
|
|
44
|
-
expected_result: |
|
|
45
|
-
{"utm_campaign":"brand_awareness","visits":2}
|
|
46
|
-
{"utm_campaign":"holiday_promo","visits":2}
|
|
47
|
-
{"utm_campaign":"product_launch","visits":2}
|
|
48
|
-
{"utm_campaign":"summer_sale_2024","visits":1}
|
|
49
|
-
{"utm_campaign":"retention_q4","visits":1}
|
|
50
|
-
{"utm_campaign":"newsletter_weekly","visits":1}
|
|
51
|
-
|
|
52
22
|
- name: Filtered by pathname - /about/
|
|
53
23
|
description: Filtered by pathname - /about/
|
|
54
24
|
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&pathname=%2Fabout%2F
|
|
@@ -103,7 +73,7 @@
|
|
|
103
73
|
|
|
104
74
|
- name: Test with multiple filters combined
|
|
105
75
|
description: Test with multiple filters combined
|
|
106
|
-
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&
|
|
76
|
+
parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&source=bing.com&pathname=%2Fabout%2F
|
|
107
77
|
expected_result: |
|
|
108
|
-
{"utm_campaign":"
|
|
109
|
-
{"utm_campaign":"
|
|
78
|
+
{"utm_campaign":"retention_q4","visits":1}
|
|
79
|
+
{"utm_campaign":"newsletter_weekly","visits":1}
|