ghost 6.0.6 → 6.0.8

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 (53) hide show
  1. package/components/tryghost-i18n-6.0.8.tgz +0 -0
  2. package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +2 -2
  3. package/core/built/admin/assets/admin-x-activitypub/{index-BRzGrD-C.mjs → index-1EXYCtPI.mjs} +26876 -22657
  4. package/core/built/admin/assets/admin-x-activitypub/{index-Co80faUx.mjs → index-If44c6h0.mjs} +2 -2
  5. package/core/built/admin/assets/admin-x-settings/{CodeEditorView-B4W7CQcA.mjs → CodeEditorView-CzXlGImM.mjs} +2 -2
  6. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +1 -1
  7. package/core/built/admin/assets/admin-x-settings/{index-Bmm3Xeuw.mjs → index-BgCSf8S1.mjs} +4 -5
  8. package/core/built/admin/assets/admin-x-settings/{index-CuwMM9FM.mjs → index-D2pIApbM.mjs} +26 -11
  9. package/core/built/admin/assets/admin-x-settings/{index-jv9DN3ZO.mjs → index-RKA3H0Lh.mjs} +2 -2
  10. package/core/built/admin/assets/admin-x-settings/{modals-CUGEPPYA.mjs → modals-D0f6kxWg.mjs} +2 -2
  11. package/core/built/admin/assets/{chunk.524.56bb70d3e8660d34aef1.js → chunk.524.099dcd3975a0e60c5579.js} +6 -6
  12. package/core/built/admin/assets/{chunk.582.ae0341229e71a85d0b2d.js → chunk.582.6830378a89a17aeedd0b.js} +8 -8
  13. package/core/built/admin/assets/{ghost-2bcbd118a8ad45fed5401e84a7e87c9a.js → ghost-138bb4718f8b9d666bdd7a2b45330d58.js} +34 -33
  14. package/core/built/admin/assets/{ghost-2c537ee89c36199137eafc1768fd7de8.css → ghost-a7a53bf80dc45c37ae9c174a0d02a882.css} +1 -1
  15. package/core/built/admin/assets/{ghost-dark-ad23efc1d702e3643a8ee90d089df5d6.css → ghost-dark-6e0062029f988d8676e87f22d8e7f4a3.css} +1 -1
  16. package/core/built/admin/assets/posts/posts.js +83336 -82274
  17. package/core/built/admin/assets/stats/stats.js +26957 -26799
  18. package/core/built/admin/index.html +4 -4
  19. package/core/frontend/helpers/ghost_head.js +9 -9
  20. package/core/frontend/public/ghost-stats.min.js +3 -3
  21. package/core/frontend/public/member-attribution.min.js +1 -1
  22. package/core/frontend/src/ghost-stats/ghost-stats.js +18 -4
  23. package/core/frontend/src/member-attribution/member-attribution.js +28 -18
  24. package/core/frontend/src/utils/url-attribution.js +53 -40
  25. package/core/server/api/endpoints/utils/serializers/input/posts.js +7 -5
  26. package/core/server/data/tinybird/endpoints/api_top_utm_campaigns.pipe +31 -0
  27. package/core/server/data/tinybird/endpoints/api_top_utm_contents.pipe +31 -0
  28. package/core/server/data/tinybird/endpoints/api_top_utm_mediums.pipe +31 -0
  29. package/core/server/data/tinybird/endpoints/api_top_utm_sources.pipe +31 -0
  30. package/core/server/data/tinybird/endpoints/api_top_utm_terms.pipe +31 -0
  31. package/core/server/data/tinybird/tests/api_top_utm_campaigns.yaml +108 -0
  32. package/core/server/data/tinybird/tests/api_top_utm_contents.yaml +108 -0
  33. package/core/server/data/tinybird/tests/api_top_utm_mediums.yaml +108 -0
  34. package/core/server/data/tinybird/tests/api_top_utm_sources.yaml +108 -0
  35. package/core/server/data/tinybird/tests/api_top_utm_terms.yaml +108 -0
  36. package/core/server/services/lib/magic-link/MagicLink.js +17 -11
  37. package/core/server/services/members/MembersConfigProvider.js +11 -1
  38. package/core/server/services/members/SingleUseTokenProvider.js +159 -6
  39. package/core/server/services/members/api.js +1 -1
  40. package/core/server/services/members/emails/signin.js +9 -5
  41. package/core/server/services/members/members-api/controllers/RouterController.js +95 -19
  42. package/core/server/services/members/members-api/members-api.js +8 -4
  43. package/core/server/services/members/members-ssr.js +5 -3
  44. package/core/server/services/members/middleware.js +2 -2
  45. package/core/server/services/tinybird/TinybirdService.js +6 -1
  46. package/core/server/services/update-check/UpdateCheckService.js +1 -1
  47. package/core/server/web/members/app.js +12 -3
  48. package/core/shared/config/defaults.json +1 -1
  49. package/core/shared/labs.js +3 -1
  50. package/package.json +7 -7
  51. package/tsconfig.tsbuildinfo +1 -1
  52. package/yarn.lock +380 -104
  53. package/components/tryghost-i18n-6.0.6.tgz +0 -0
@@ -3,63 +3,76 @@
3
3
  */
4
4
 
5
5
  /**
6
- * Parses URL parameters to extract attribution information
7
- *
8
- * @param {string} url - The URL to parse
9
- * @returns {Object} Parsed attribution data
6
+ * @typedef {Object} AttributionData
7
+ * @property {string|null} source - Primary attribution source (ref || source || utm_source)
8
+ * @property {string|null} medium - UTM medium parameter
9
+ * @property {string|null} url - Browser's document.referrer
10
+ * @property {string|null} utmSource - UTM source parameter
11
+ * @property {string|null} utmMedium - UTM medium parameter
12
+ * @property {string|null} utmTerm - UTM term/keyword parameter
13
+ * @property {string|null} utmCampaign - UTM campaign parameter
14
+ * @property {string|null} utmContent - UTM content/variant parameter
10
15
  */
11
- export function parseReferrer(url) {
12
- // Extract current URL parameters
13
- const currentUrl = new URL(url || window.location.href);
14
-
15
- // Parse source parameters
16
- const refParam = currentUrl.searchParams.get('ref');
17
- const sourceParam = currentUrl.searchParams.get('source');
18
- const utmSourceParam = currentUrl.searchParams.get('utm_source');
19
- const utmMediumParam = currentUrl.searchParams.get('utm_medium');
16
+
17
+ /**
18
+ * Extracts attribution parameters from URL search params
19
+ * @private
20
+ * @param {URLSearchParams} searchParams - The search params to parse
21
+ * @returns {AttributionData} Parsed attribution data with all UTM parameters
22
+ */
23
+ function extractParams(searchParams) {
24
+ const refParam = searchParams.get('ref');
25
+ const sourceParam = searchParams.get('source');
26
+ const utmSourceParam = searchParams.get('utm_source');
27
+ const utmMediumParam = searchParams.get('utm_medium');
28
+ const utmTermParam = searchParams.get('utm_term');
29
+ const utmCampaignParam = searchParams.get('utm_campaign');
30
+ const utmContentParam = searchParams.get('utm_content');
20
31
 
21
32
  // Determine primary source
22
33
  const referrerSource = refParam || sourceParam || utmSourceParam || null;
23
34
 
24
- // Check portal hash if needed
25
- if (!referrerSource && currentUrl.hash && currentUrl.hash.includes('#/portal')) {
26
- return parsePortalHash(currentUrl);
27
- }
28
-
29
35
  return {
30
36
  source: referrerSource,
31
37
  medium: utmMediumParam || null,
32
- url: window.document.referrer || null
38
+ url: window.document.referrer || null,
39
+ utmSource: utmSourceParam || null,
40
+ utmMedium: utmMediumParam || null,
41
+ utmTerm: utmTermParam || null,
42
+ utmCampaign: utmCampaignParam || null,
43
+ utmContent: utmContentParam || null
33
44
  };
34
45
  }
35
46
 
36
47
  /**
37
- * Parses attribution data from portal hash URLs
48
+ * Parses URL parameters to extract complete referrer/attribution data
38
49
  *
39
- * @param {URL} url - URL object with a portal hash
40
- * @returns {Object} Parsed attribution data
50
+ * @param {string} url - The URL to parse (defaults to current URL)
51
+ * @returns {AttributionData} Complete attribution data including all UTM parameters
41
52
  */
42
- export function parsePortalHash(url) {
43
- const hashUrl = new URL(url.href.replace('/#/portal', ''));
44
- const refParam = hashUrl.searchParams.get('ref');
45
- const sourceParam = hashUrl.searchParams.get('source');
46
- const utmSourceParam = hashUrl.searchParams.get('utm_source');
47
- const utmMediumParam = hashUrl.searchParams.get('utm_medium');
53
+ export function parseReferrerData(url) {
54
+ // Extract current URL parameters
55
+ const currentUrl = new URL(url || window.location.href);
56
+ let searchParams = currentUrl.searchParams;
48
57
 
49
- return {
50
- source: refParam || sourceParam || utmSourceParam || null,
51
- medium: utmMediumParam || null,
52
- url: window.document.referrer || null
53
- };
58
+ // Handle portal hash URLs - extract params from hash instead
59
+ if (currentUrl.hash && currentUrl.hash.includes('#/portal')) {
60
+ const hashUrl = new URL(currentUrl.href.replace('/#/portal', ''));
61
+ searchParams = hashUrl.searchParams;
62
+ }
63
+
64
+ return extractParams(searchParams);
54
65
  }
55
66
 
56
67
  /**
57
- * Gets the final referrer value based on parsed data
58
- *
59
- * @param {Object} referrerData - Parsed referrer data
60
- * @returns {string|null} Final referrer value or null
68
+ * Selects the primary referrer value from parsed attribution data
69
+ * Prioritizes: source → medium → url
70
+ * Filters out same-domain referrers
71
+ * @private
72
+ * @param {AttributionData} referrerData - Parsed referrer data
73
+ * @returns {string|null} Primary referrer value or null
61
74
  */
62
- export function getFinalReferrer(referrerData) {
75
+ function selectPrimaryReferrer(referrerData) {
63
76
  const { source, medium, url } = referrerData;
64
77
  const finalReferrer = source || medium || url || null;
65
78
 
@@ -87,6 +100,6 @@ export function getFinalReferrer(referrerData) {
87
100
  * @returns {string|null} Final referrer value
88
101
  */
89
102
  export function getReferrer(url) {
90
- const referrerData = parseReferrer(url);
91
- return getFinalReferrer(referrerData);
103
+ const referrerData = parseReferrerData(url);
104
+ return selectPrimaryReferrer(referrerData);
92
105
  }
@@ -19,10 +19,10 @@ const messages = {
19
19
 
20
20
  /**
21
21
  * Selects all allowed columns for the given frame.
22
- *
22
+ *
23
23
  * NOTE: This doesn't stop them from being FETCHED, just returned in the response. This causes
24
24
  * the output serializer to remove them from the data object before returning.
25
- *
25
+ *
26
26
  * NOTE: This is only intended for the Content API. We need these fields within Admin API responses.
27
27
  *
28
28
  * @param {Object} frame - The frame object.
@@ -37,10 +37,10 @@ function removeSourceFormats(frame) {
37
37
 
38
38
  /**
39
39
  * Selects all allowed columns for the given frame.
40
- *
40
+ *
41
41
  * This removes the lexical and mobiledoc columns from the query. This is a performance improvement as we never intend
42
42
  * to expose those columns in the content API and they are very large datasets to be passing around and de/serializing.
43
- *
43
+ *
44
44
  * NOTE: This is only intended for the Content API. We need these fields within Admin API responses.
45
45
  *
46
46
  * @param {Object} frame - The frame object.
@@ -97,7 +97,9 @@ function setDefaultOrder(frame) {
97
97
  }
98
98
 
99
99
  if (!frame.options.order && !frame.options.autoOrder) {
100
- frame.options.order = 'published_at desc';
100
+ // use id as fallback to ensure consistent ordering across pages when posts
101
+ // have the same published_at timestamp
102
+ frame.options.order = 'published_at desc, id desc';
101
103
  }
102
104
  }
103
105
 
@@ -0,0 +1,31 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE top_utm_campaigns
4
+ SQL >
5
+ %
6
+ select
7
+ case
8
+ when length(source) % 6 = 0 then 'summer_sale_2024'
9
+ when length(source) % 6 = 1 then 'newsletter_weekly'
10
+ when length(source) % 6 = 2 then 'product_launch'
11
+ when length(source) % 6 = 3 then 'holiday_promo'
12
+ when length(source) % 6 = 4 then 'brand_awareness'
13
+ when length(source) % 6 = 5 then 'retention_q4'
14
+ end as utm_campaign,
15
+ count() as visits
16
+ from mv_session_data sd
17
+ inner join filtered_sessions fs
18
+ on fs.session_id = sd.session_id
19
+ where
20
+ site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
21
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
22
+ and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) = {{ Date(date_from) }}
23
+ {% else %}
24
+ {% if defined(date_from) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= {{ Date(date_from) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= timestampAdd(today(), interval -7 day) {% end %}
25
+ {% if defined(date_to) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= {{ Date(date_to) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= today() {% end %}
26
+ {% end %}
27
+ group by utm_campaign
28
+ order by visits desc
29
+ limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }}
30
+
31
+ TYPE ENDPOINT
@@ -0,0 +1,31 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE top_utm_content
4
+ SQL >
5
+ %
6
+ select
7
+ case
8
+ when length(source) % 6 = 0 then 'hero-banner'
9
+ when length(source) % 6 = 1 then 'sidebar-cta'
10
+ when length(source) % 6 = 2 then 'footer-link'
11
+ when length(source) % 6 = 3 then 'button-primary'
12
+ when length(source) % 6 = 4 then 'text-link'
13
+ when length(source) % 6 = 5 then 'nav-menu'
14
+ end as utm_content,
15
+ count() as visits
16
+ from mv_session_data sd
17
+ inner join filtered_sessions fs
18
+ on fs.session_id = sd.session_id
19
+ where
20
+ site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
21
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
22
+ and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) = {{ Date(date_from) }}
23
+ {% else %}
24
+ {% if defined(date_from) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= {{ Date(date_from) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= timestampAdd(today(), interval -7 day) {% end %}
25
+ {% if defined(date_to) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= {{ Date(date_to) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= today() {% end %}
26
+ {% end %}
27
+ group by utm_content
28
+ order by visits desc
29
+ limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }}
30
+
31
+ TYPE ENDPOINT
@@ -0,0 +1,31 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE top_utm_mediums
4
+ SQL >
5
+ %
6
+ select
7
+ case
8
+ when length(source) % 6 = 0 then 'email'
9
+ when length(source) % 6 = 1 then 'social'
10
+ when length(source) % 6 = 2 then 'cpc'
11
+ when length(source) % 6 = 3 then 'organic'
12
+ when length(source) % 6 = 4 then 'referral'
13
+ when length(source) % 6 = 5 then 'display'
14
+ end as utm_medium,
15
+ count() as visits
16
+ from mv_session_data sd
17
+ inner join filtered_sessions fs
18
+ on fs.session_id = sd.session_id
19
+ where
20
+ site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
21
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
22
+ and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) = {{ Date(date_from) }}
23
+ {% else %}
24
+ {% if defined(date_from) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= {{ Date(date_from) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= timestampAdd(today(), interval -7 day) {% end %}
25
+ {% if defined(date_to) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= {{ Date(date_to) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= today() {% end %}
26
+ {% end %}
27
+ group by utm_medium
28
+ order by visits desc
29
+ limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }}
30
+
31
+ TYPE ENDPOINT
@@ -0,0 +1,31 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE top_utm_sources
4
+ SQL >
5
+ %
6
+ select
7
+ case
8
+ when length(source) % 6 = 0 then 'google'
9
+ when length(source) % 6 = 1 then 'facebook'
10
+ when length(source) % 6 = 2 then 'twitter'
11
+ when length(source) % 6 = 3 then 'linkedin'
12
+ when length(source) % 6 = 4 then 'newsletter'
13
+ when length(source) % 6 = 5 then 'instagram'
14
+ end as utm_source,
15
+ count() as visits
16
+ from mv_session_data sd
17
+ inner join filtered_sessions fs
18
+ on fs.session_id = sd.session_id
19
+ where
20
+ site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
21
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
22
+ and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) = {{ Date(date_from) }}
23
+ {% else %}
24
+ {% if defined(date_from) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= {{ Date(date_from) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= timestampAdd(today(), interval -7 day) {% end %}
25
+ {% if defined(date_to) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= {{ Date(date_to) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= today() {% end %}
26
+ {% end %}
27
+ group by utm_source
28
+ order by visits desc
29
+ limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }}
30
+
31
+ TYPE ENDPOINT
@@ -0,0 +1,31 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE top_utm_terms
4
+ SQL >
5
+ %
6
+ select
7
+ case
8
+ when length(source) % 6 = 0 then 'ghost cms'
9
+ when length(source) % 6 = 1 then 'headless publishing'
10
+ when length(source) % 6 = 2 then 'content management'
11
+ when length(source) % 6 = 3 then 'newsletter platform'
12
+ when length(source) % 6 = 4 then 'blog software'
13
+ when length(source) % 6 = 5 then 'membership site'
14
+ end as utm_term,
15
+ count() as visits
16
+ from mv_session_data sd
17
+ inner join filtered_sessions fs
18
+ on fs.session_id = sd.session_id
19
+ where
20
+ site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
21
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
22
+ and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) = {{ Date(date_from) }}
23
+ {% else %}
24
+ {% if defined(date_from) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= {{ Date(date_from) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= timestampAdd(today(), interval -7 day) {% end %}
25
+ {% if defined(date_to) %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= {{ Date(date_to) }} {% else %} and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) <= today() {% end %}
26
+ {% end %}
27
+ group by utm_term
28
+ order by visits desc
29
+ limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }}
30
+
31
+ TYPE ENDPOINT
@@ -0,0 +1,108 @@
1
+
2
+ - name: Date range
3
+ description: All fixture data
4
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC
5
+ expected_result: |
6
+ {"utm_campaign":"summer_sale_2024","visits":6}
7
+ {"utm_campaign":"brand_awareness","visits":3}
8
+ {"utm_campaign":"holiday_promo","visits":3}
9
+ {"utm_campaign":"product_launch","visits":3}
10
+ {"utm_campaign":"retention_q4","visits":1}
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
+ {"utm_campaign":"summer_sale_2024","visits":4}
17
+ {"utm_campaign":"brand_awareness","visits":1}
18
+ {"utm_campaign":"holiday_promo","visits":1}
19
+ {"utm_campaign":"product_launch","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":"summer_sale_2024","visits":6}
26
+ {"utm_campaign":"brand_awareness","visits":3}
27
+ {"utm_campaign":"product_launch","visits":3}
28
+ {"utm_campaign":"holiday_promo","visits":2}
29
+ {"utm_campaign":"retention_q4","visits":1}
30
+
31
+ - name: Filtered by location - UK
32
+ description: Filtered by location - UK
33
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&location=GB
34
+ expected_result: |
35
+ {"utm_campaign":"summer_sale_2024","visits":3}
36
+ {"utm_campaign":"brand_awareness","visits":2}
37
+ {"utm_campaign":"holiday_promo","visits":2}
38
+ {"utm_campaign":"product_launch","visits":1}
39
+
40
+ - name: Filtered by OS - Windows
41
+ description: Filtered by OS - Windows
42
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&os=windows
43
+ expected_result: |
44
+ {"utm_campaign":"summer_sale_2024","visits":5}
45
+ {"utm_campaign":"brand_awareness","visits":3}
46
+ {"utm_campaign":"product_launch","visits":3}
47
+ {"utm_campaign":"holiday_promo","visits":2}
48
+ {"utm_campaign":"retention_q4","visits":1}
49
+
50
+ - name: Filtered by pathname - /about/
51
+ description: Filtered by pathname - /about/
52
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&pathname=%2Fabout%2F
53
+ expected_result: |
54
+ {"utm_campaign":"summer_sale_2024","visits":4}
55
+ {"utm_campaign":"product_launch","visits":2}
56
+ {"utm_campaign":"brand_awareness","visits":1}
57
+ {"utm_campaign":"holiday_promo","visits":1}
58
+
59
+ - name: Filtered by post_uuid - 06b1b0c9-fb53-4a15-a060-3db3fde7b1fc (/about/)
60
+ description: Filtered by post_uuid - 06b1b0c9-fb53-4a15-a060-3db3fde7b1fc (/about/)
61
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&post_uuid=06b1b0c9-fb53-4a15-a060-3db3fde7b1fc
62
+ expected_result: |
63
+ {"utm_campaign":"summer_sale_2024","visits":4}
64
+ {"utm_campaign":"product_launch","visits":2}
65
+ {"utm_campaign":"brand_awareness","visits":1}
66
+ {"utm_campaign":"holiday_promo","visits":1}
67
+
68
+ - name: Filtered by source - bing.com
69
+ description: Filtered by source - bing.com
70
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&source=bing.com
71
+ expected_result: |
72
+ {"utm_campaign":"product_launch","visits":2}
73
+
74
+ - name: Filtered by member status - paid
75
+ description: Filtered by member status - paid
76
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&member_status=paid
77
+ expected_result: |
78
+ {"utm_campaign":"brand_awareness","visits":2}
79
+ {"utm_campaign":"summer_sale_2024","visits":2}
80
+ {"utm_campaign":"product_launch","visits":1}
81
+
82
+ - name: Filtered by member status - undefined
83
+ description: Filtered by member status - undefined
84
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&member_status=undefined
85
+ expected_result: |
86
+ {"utm_campaign":"holiday_promo","visits":3}
87
+ {"utm_campaign":"brand_awareness","visits":1}
88
+ {"utm_campaign":"summer_sale_2024","visits":1}
89
+ {"utm_campaign":"retention_q4","visits":1}
90
+
91
+ - name: Filtered by timezone - America/Los_Angeles
92
+ description: Filtered by timezone - America/Los_Angeles
93
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=America/Los_Angeles
94
+ expected_result: |
95
+ {"utm_campaign":"summer_sale_2024","visits":5}
96
+ {"utm_campaign":"brand_awareness","visits":3}
97
+ {"utm_campaign":"holiday_promo","visits":2}
98
+ {"utm_campaign":"product_launch","visits":2}
99
+ {"utm_campaign":"retention_q4","visits":1}
100
+
101
+ - name: Test with multiple filters combined
102
+ description: Test with multiple filters combined
103
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&device=desktop&browser=firefox
104
+ expected_result: |
105
+ {"utm_campaign":"brand_awareness","visits":2}
106
+ {"utm_campaign":"retention_q4","visits":1}
107
+ {"utm_campaign":"holiday_promo","visits":1}
108
+ {"utm_campaign":"product_launch","visits":1}
@@ -0,0 +1,108 @@
1
+
2
+ - name: Date range
3
+ description: All fixture data
4
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC
5
+ expected_result: |
6
+ {"utm_content":"hero-banner","visits":6}
7
+ {"utm_content":"footer-link","visits":3}
8
+ {"utm_content":"text-link","visits":3}
9
+ {"utm_content":"button-primary","visits":3}
10
+ {"utm_content":"nav-menu","visits":1}
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
+ {"utm_content":"hero-banner","visits":4}
17
+ {"utm_content":"footer-link","visits":1}
18
+ {"utm_content":"text-link","visits":1}
19
+ {"utm_content":"button-primary","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_content":"hero-banner","visits":6}
26
+ {"utm_content":"footer-link","visits":3}
27
+ {"utm_content":"text-link","visits":3}
28
+ {"utm_content":"button-primary","visits":2}
29
+ {"utm_content":"nav-menu","visits":1}
30
+
31
+ - name: Filtered by location - UK
32
+ description: Filtered by location - UK
33
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&location=GB
34
+ expected_result: |
35
+ {"utm_content":"hero-banner","visits":3}
36
+ {"utm_content":"text-link","visits":2}
37
+ {"utm_content":"button-primary","visits":2}
38
+ {"utm_content":"footer-link","visits":1}
39
+
40
+ - name: Filtered by OS - Windows
41
+ description: Filtered by OS - Windows
42
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&os=windows
43
+ expected_result: |
44
+ {"utm_content":"hero-banner","visits":5}
45
+ {"utm_content":"footer-link","visits":3}
46
+ {"utm_content":"text-link","visits":3}
47
+ {"utm_content":"button-primary","visits":2}
48
+ {"utm_content":"nav-menu","visits":1}
49
+
50
+ - name: Filtered by pathname - /about/
51
+ description: Filtered by pathname - /about/
52
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&pathname=%2Fabout%2F
53
+ expected_result: |
54
+ {"utm_content":"hero-banner","visits":4}
55
+ {"utm_content":"footer-link","visits":2}
56
+ {"utm_content":"text-link","visits":1}
57
+ {"utm_content":"button-primary","visits":1}
58
+
59
+ - name: Filtered by post_uuid - 06b1b0c9-fb53-4a15-a060-3db3fde7b1fc (/about/)
60
+ description: Filtered by post_uuid - 06b1b0c9-fb53-4a15-a060-3db3fde7b1fc (/about/)
61
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&post_uuid=06b1b0c9-fb53-4a15-a060-3db3fde7b1fc
62
+ expected_result: |
63
+ {"utm_content":"hero-banner","visits":4}
64
+ {"utm_content":"footer-link","visits":2}
65
+ {"utm_content":"text-link","visits":1}
66
+ {"utm_content":"button-primary","visits":1}
67
+
68
+ - name: Filtered by source - bing.com
69
+ description: Filtered by source - bing.com
70
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&source=bing.com
71
+ expected_result: |
72
+ {"utm_content":"footer-link","visits":2}
73
+
74
+ - name: Filtered by member status - paid
75
+ description: Filtered by member status - paid
76
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&member_status=paid
77
+ expected_result: |
78
+ {"utm_content":"text-link","visits":2}
79
+ {"utm_content":"hero-banner","visits":2}
80
+ {"utm_content":"footer-link","visits":1}
81
+
82
+ - name: Filtered by member status - undefined
83
+ description: Filtered by member status - undefined
84
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&member_status=undefined
85
+ expected_result: |
86
+ {"utm_content":"button-primary","visits":3}
87
+ {"utm_content":"nav-menu","visits":1}
88
+ {"utm_content":"text-link","visits":1}
89
+ {"utm_content":"hero-banner","visits":1}
90
+
91
+ - name: Filtered by timezone - America/Los_Angeles
92
+ description: Filtered by timezone - America/Los_Angeles
93
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=America/Los_Angeles
94
+ expected_result: |
95
+ {"utm_content":"hero-banner","visits":5}
96
+ {"utm_content":"text-link","visits":3}
97
+ {"utm_content":"footer-link","visits":2}
98
+ {"utm_content":"button-primary","visits":2}
99
+ {"utm_content":"nav-menu","visits":1}
100
+
101
+ - name: Test with multiple filters combined
102
+ description: Test with multiple filters combined
103
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&device=desktop&browser=firefox
104
+ expected_result: |
105
+ {"utm_content":"text-link","visits":2}
106
+ {"utm_content":"nav-menu","visits":1}
107
+ {"utm_content":"footer-link","visits":1}
108
+ {"utm_content":"button-primary","visits":1}
@@ -0,0 +1,108 @@
1
+
2
+ - name: Date range
3
+ description: All fixture data
4
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC
5
+ expected_result: |
6
+ {"utm_medium":"email","visits":6}
7
+ {"utm_medium":"cpc","visits":3}
8
+ {"utm_medium":"organic","visits":3}
9
+ {"utm_medium":"referral","visits":3}
10
+ {"utm_medium":"display","visits":1}
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
+ {"utm_medium":"email","visits":4}
17
+ {"utm_medium":"cpc","visits":1}
18
+ {"utm_medium":"organic","visits":1}
19
+ {"utm_medium":"referral","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_medium":"email","visits":6}
26
+ {"utm_medium":"cpc","visits":3}
27
+ {"utm_medium":"referral","visits":3}
28
+ {"utm_medium":"organic","visits":2}
29
+ {"utm_medium":"display","visits":1}
30
+
31
+ - name: Filtered by location - UK
32
+ description: Filtered by location - UK
33
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&location=GB
34
+ expected_result: |
35
+ {"utm_medium":"email","visits":3}
36
+ {"utm_medium":"organic","visits":2}
37
+ {"utm_medium":"referral","visits":2}
38
+ {"utm_medium":"cpc","visits":1}
39
+
40
+ - name: Filtered by OS - Windows
41
+ description: Filtered by OS - Windows
42
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&os=windows
43
+ expected_result: |
44
+ {"utm_medium":"email","visits":5}
45
+ {"utm_medium":"cpc","visits":3}
46
+ {"utm_medium":"referral","visits":3}
47
+ {"utm_medium":"organic","visits":2}
48
+ {"utm_medium":"display","visits":1}
49
+
50
+ - name: Filtered by pathname - /about/
51
+ description: Filtered by pathname - /about/
52
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&pathname=%2Fabout%2F
53
+ expected_result: |
54
+ {"utm_medium":"email","visits":4}
55
+ {"utm_medium":"cpc","visits":2}
56
+ {"utm_medium":"organic","visits":1}
57
+ {"utm_medium":"referral","visits":1}
58
+
59
+ - name: Filtered by post_uuid - 06b1b0c9-fb53-4a15-a060-3db3fde7b1fc (/about/)
60
+ description: Filtered by post_uuid - 06b1b0c9-fb53-4a15-a060-3db3fde7b1fc (/about/)
61
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&post_uuid=06b1b0c9-fb53-4a15-a060-3db3fde7b1fc
62
+ expected_result: |
63
+ {"utm_medium":"email","visits":4}
64
+ {"utm_medium":"cpc","visits":2}
65
+ {"utm_medium":"organic","visits":1}
66
+ {"utm_medium":"referral","visits":1}
67
+
68
+ - name: Filtered by source - bing.com
69
+ description: Filtered by source - bing.com
70
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&source=bing.com
71
+ expected_result: |
72
+ {"utm_medium":"cpc","visits":2}
73
+
74
+ - name: Filtered by member status - paid
75
+ description: Filtered by member status - paid
76
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&member_status=paid
77
+ expected_result: |
78
+ {"utm_medium":"referral","visits":2}
79
+ {"utm_medium":"email","visits":2}
80
+ {"utm_medium":"cpc","visits":1}
81
+
82
+ - name: Filtered by member status - undefined
83
+ description: Filtered by member status - undefined
84
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&member_status=undefined
85
+ expected_result: |
86
+ {"utm_medium":"organic","visits":3}
87
+ {"utm_medium":"referral","visits":1}
88
+ {"utm_medium":"display","visits":1}
89
+ {"utm_medium":"email","visits":1}
90
+
91
+ - name: Filtered by timezone - America/Los_Angeles
92
+ description: Filtered by timezone - America/Los_Angeles
93
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=America/Los_Angeles
94
+ expected_result: |
95
+ {"utm_medium":"email","visits":5}
96
+ {"utm_medium":"referral","visits":3}
97
+ {"utm_medium":"cpc","visits":2}
98
+ {"utm_medium":"organic","visits":2}
99
+ {"utm_medium":"display","visits":1}
100
+
101
+ - name: Test with multiple filters combined
102
+ description: Test with multiple filters combined
103
+ parameters: site_uuid=mock_site_uuid&date_from=2100-01-01&date_to=2100-01-07&timezone=Etc/UTC&device=desktop&browser=firefox
104
+ expected_result: |
105
+ {"utm_medium":"referral","visits":2}
106
+ {"utm_medium":"cpc","visits":1}
107
+ {"utm_medium":"organic","visits":1}
108
+ {"utm_medium":"display","visits":1}