ghost 5.116.0 → 5.116.2

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 (85) hide show
  1. package/components/{tryghost-api-framework-5.116.0.tgz → tryghost-api-framework-5.116.2.tgz} +0 -0
  2. package/components/tryghost-constants-5.116.2.tgz +0 -0
  3. package/components/tryghost-custom-fonts-5.116.2.tgz +0 -0
  4. package/components/{tryghost-custom-theme-settings-service-5.116.0.tgz → tryghost-custom-theme-settings-service-5.116.2.tgz} +0 -0
  5. package/components/tryghost-domain-events-5.116.2.tgz +0 -0
  6. package/components/tryghost-donations-5.116.2.tgz +0 -0
  7. package/components/{tryghost-email-addresses-5.116.0.tgz → tryghost-email-addresses-5.116.2.tgz} +0 -0
  8. package/components/{tryghost-email-service-5.116.0.tgz → tryghost-email-service-5.116.2.tgz} +0 -0
  9. package/components/tryghost-email-suppression-list-5.116.2.tgz +0 -0
  10. package/components/{tryghost-html-to-plaintext-5.116.0.tgz → tryghost-html-to-plaintext-5.116.2.tgz} +0 -0
  11. package/components/tryghost-i18n-5.116.2.tgz +0 -0
  12. package/components/{tryghost-job-manager-5.116.0.tgz → tryghost-job-manager-5.116.2.tgz} +0 -0
  13. package/components/tryghost-link-replacer-5.116.2.tgz +0 -0
  14. package/components/{tryghost-magic-link-5.116.0.tgz → tryghost-magic-link-5.116.2.tgz} +0 -0
  15. package/components/{tryghost-member-attribution-5.116.0.tgz → tryghost-member-attribution-5.116.2.tgz} +0 -0
  16. package/components/{tryghost-member-events-5.116.0.tgz → tryghost-member-events-5.116.2.tgz} +0 -0
  17. package/components/{tryghost-members-api-5.116.0.tgz → tryghost-members-api-5.116.2.tgz} +0 -0
  18. package/components/{tryghost-members-csv-5.116.0.tgz → tryghost-members-csv-5.116.2.tgz} +0 -0
  19. package/components/{tryghost-members-offers-5.116.0.tgz → tryghost-members-offers-5.116.2.tgz} +0 -0
  20. package/components/tryghost-milestones-5.116.2.tgz +0 -0
  21. package/components/{tryghost-mw-error-handler-5.116.0.tgz → tryghost-mw-error-handler-5.116.2.tgz} +0 -0
  22. package/components/{tryghost-mw-vhost-5.116.0.tgz → tryghost-mw-vhost-5.116.2.tgz} +0 -0
  23. package/components/tryghost-post-events-5.116.2.tgz +0 -0
  24. package/components/tryghost-post-revisions-5.116.2.tgz +0 -0
  25. package/components/tryghost-posts-service-5.116.2.tgz +0 -0
  26. package/components/{tryghost-prometheus-metrics-5.116.0.tgz → tryghost-prometheus-metrics-5.116.2.tgz} +0 -0
  27. package/components/tryghost-security-5.116.2.tgz +0 -0
  28. package/components/{tryghost-tiers-5.116.0.tgz → tryghost-tiers-5.116.2.tgz} +0 -0
  29. package/components/tryghost-webmentions-5.116.2.tgz +0 -0
  30. package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +9776 -11013
  31. package/core/built/admin/assets/admin-x-demo/admin-x-demo.js +2 -2
  32. package/core/built/admin/assets/admin-x-demo/{index-a9601514.mjs → index-09325f38.mjs} +4 -4
  33. package/core/built/admin/assets/admin-x-demo/{modals-c1789d04.mjs → modals-1a9ae8b7.mjs} +2 -2
  34. package/core/built/admin/assets/admin-x-settings/{CodeEditorView-e9c9deb8.mjs → CodeEditorView-550846e0.mjs} +2 -2
  35. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +2 -2
  36. package/core/built/admin/assets/admin-x-settings/{index-f744cab7.mjs → index-4ce2fcd1.mjs} +78 -77
  37. package/core/built/admin/assets/admin-x-settings/{index-84580c3a.mjs → index-f3cb3f4d.mjs} +2 -2
  38. package/core/built/admin/assets/admin-x-settings/{modals-d9ca60c5.mjs → modals-6bc20529.mjs} +8 -8
  39. package/core/built/admin/assets/{chunk.524.8371443ef8f60db429d0.js → chunk.524.578de86e5014b911b05a.js} +8 -8
  40. package/core/built/admin/assets/{chunk.582.f90151775f2e53dd21d9.js → chunk.582.21bf3e37b5d84ac4b58a.js} +9 -9
  41. package/core/built/admin/assets/{chunk.713.e9027c0cc3c56110f5da.js → chunk.713.761d11035fe0bf3e557c.js} +2 -2
  42. package/core/built/admin/assets/{ghost-03b64c086f3c60cabc85fe7a7e2b640a.js → ghost-868c537d5c02ca65323d0122596a67ec.js} +57 -55
  43. package/core/built/admin/assets/posts/posts.js +5185 -5096
  44. package/core/built/admin/assets/stats/stats.js +6630 -6541
  45. package/core/built/admin/assets/{vendor-72026232b36d97babc6320917c16c321.js → vendor-8e3ee8261528bb429cfe78ce79a4a82a.js} +5 -5
  46. package/core/built/admin/index.html +5 -5
  47. package/core/frontend/helpers/ghost_head.js +9 -5
  48. package/core/frontend/public/ghost-stats.js +41 -74
  49. package/core/server/data/tinybird/datasources/_mv_hits.datasource +23 -0
  50. package/core/server/data/tinybird/datasources/analytics_events.datasource +14 -0
  51. package/core/server/data/tinybird/endpoints/api_kpis.pipe +161 -0
  52. package/core/server/data/tinybird/endpoints/api_top_browsers.pipe +52 -0
  53. package/core/server/data/tinybird/endpoints/api_top_devices.pipe +51 -0
  54. package/core/server/data/tinybird/endpoints/api_top_locations.pipe +51 -0
  55. package/core/server/data/tinybird/endpoints/api_top_os.pipe +51 -0
  56. package/core/server/data/tinybird/endpoints/api_top_pages.pipe +52 -0
  57. package/core/server/data/tinybird/endpoints/api_top_sources.pipe +24 -0
  58. package/core/server/data/tinybird/fixtures/analytics_events.ndjson +31 -0
  59. package/core/server/data/tinybird/pipes/filtered_sessions.pipe +42 -0
  60. package/core/server/data/tinybird/pipes/mv_hits.pipe +89 -0
  61. package/core/server/data/tinybird/pipes/mv_session_data.pipe +28 -0
  62. package/core/server/data/tinybird/readme.md +47 -0
  63. package/core/server/data/tinybird/tests/api_kpis.yaml +207 -0
  64. package/core/server/data/tinybird/tests/api_top_browsers.yaml +89 -0
  65. package/core/server/data/tinybird/tests/api_top_devices.yaml +69 -0
  66. package/core/server/data/tinybird/tests/api_top_locations.yaml +95 -0
  67. package/core/server/data/tinybird/tests/api_top_os.yaml +73 -0
  68. package/core/server/data/tinybird/tests/api_top_pages.yaml +86 -0
  69. package/core/server/data/tinybird/tests/api_top_sources.yaml +118 -0
  70. package/package.json +59 -59
  71. package/yarn.lock +37 -56
  72. package/components/tryghost-constants-5.116.0.tgz +0 -0
  73. package/components/tryghost-custom-fonts-5.116.0.tgz +0 -0
  74. package/components/tryghost-domain-events-5.116.0.tgz +0 -0
  75. package/components/tryghost-donations-5.116.0.tgz +0 -0
  76. package/components/tryghost-email-suppression-list-5.116.0.tgz +0 -0
  77. package/components/tryghost-i18n-5.116.0.tgz +0 -0
  78. package/components/tryghost-link-replacer-5.116.0.tgz +0 -0
  79. package/components/tryghost-milestones-5.116.0.tgz +0 -0
  80. package/components/tryghost-post-events-5.116.0.tgz +0 -0
  81. package/components/tryghost-post-revisions-5.116.0.tgz +0 -0
  82. package/components/tryghost-posts-service-5.116.0.tgz +0 -0
  83. package/components/tryghost-security-5.116.0.tgz +0 -0
  84. package/components/tryghost-webmentions-5.116.0.tgz +0 -0
  85. /package/core/built/admin/assets/{chunk.713.e9027c0cc3c56110f5da.js.LICENSE.txt → chunk.713.761d11035fe0bf3e557c.js.LICENSE.txt} +0 -0
@@ -8470,10 +8470,10 @@ if("object"==typeof t[n]){if(!e(t[n],r[n]))return!1}else if(t[n]!==r[n])return!1
8470
8470
  function r(e){return"object"==typeof e&&Boolean(e)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
8471
8471
  class n extends t.default{getStyles(e,t){return[].concat(...[...e.filter(r),t].map((e=>Object.entries(e).map((([e,t])=>[Ember.String.dasherize(e),t])))))}setStyles(e,t){const r=this._oldStyles||new Set
8472
8472
  t.forEach((([t,n])=>{let i=""
8473
- n&&n.includes("!important")&&(i="important",n=n.replace("!important","")),t=Ember.String.dasherize(t),e.style.setProperty(t,n,i),r.delete(t)})),r.forEach((t=>e.style.removeProperty(t))),this._oldStyles=new Set(t.map((e=>e[0])))}modify(e,t,r){this.setStyles(e,this.getStyles(t,r))}}e.default=n})),define("ember-svg-jar/helpers/svg-jar",["exports","ember-svg-jar/utils/make-svg"],(function(e,t){"use strict"
8474
- function r(e){let t=null
8475
- try{t=require(`ember-svg-jar/inlined/${e}`).default}catch(r){}try{t={}[e].default}catch(r){}return t}function n(e,n){return(0,t.default)(e,n,r)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.svgJar=n
8476
- e.default=Ember.Helper.helper((function([e],t){return n(e,t)}))})),define("ember-svg-jar/inlined/activity-placeholder",["exports"],(function(e){"use strict"
8473
+ n&&n.includes("!important")&&(i="important",n=n.replace("!important","")),t=Ember.String.dasherize(t),e.style.setProperty(t,n,i),r.delete(t)})),r.forEach((t=>e.style.removeProperty(t))),this._oldStyles=new Set(t.map((e=>e[0])))}modify(e,t,r){this.setStyles(e,this.getStyles(t,r))}}e.default=n})),define("ember-svg-jar/helpers/svg-jar",["exports","ember-svg-jar/utils/make-svg","@embroider/macros/es-compat2"],(function(e,t,r){"use strict"
8474
+ function n(e){let t=null
8475
+ try{t=require(`ember-svg-jar/inlined/${e}`).default}catch(n){}try{t=(0,r.default)(require(`../inlined/${e}`)).default}catch(n){}return t}function i(e,r){return(0,t.default)(e,r,n)}Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,e.svgJar=i
8476
+ e.default=Ember.Helper.helper((function([e],t){return i(e,t)}))})),define("ember-svg-jar/inlined/activity-placeholder",["exports"],(function(e){"use strict"
8477
8477
  Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
8478
8478
  e.default={content:'<path clip-rule="evenodd" d="M9.295.422a11 11 0 0112.924 11.614.5.5 0 11-.998-.072 10 10 0 10-9.257 9.257.5.5 0 11.072.998A11 11 0 019.295.422zm.288 4.546a6.5 6.5 0 017.961 4.657.5.5 0 11-.968.25 5.499 5.499 0 10-6.7 6.7.5.5 0 01-.251.97 6.5 6.5 0 01-.042-12.577zm1.388 5.02a1.21 1.21 0 01.725.087h.002l11.4 5.21a1.19 1.19 0 01-.163 2.187L18.92 18.94l-1.449 3.987v.002a1.18 1.18 0 01-2.117.223.5.5 0 01-.029-.054l-5.217-11.394a1.21 1.21 0 01.863-1.716zm.312.997a.21.21 0 00-.274.284l.006.013 5.203 11.363a.18.18 0 00.31-.052l.002-.004 1.53-4.21a.5.5 0 01.298-.299l4.24-1.55.017-.005a.19.19 0 00.11-.27.19.19 0 00-.066-.07l-11.375-5.2z"/>',attrs:{fill:"none",viewBox:"0 0 24 24"}}})),define("ember-svg-jar/inlined/add-view",["exports"],(function(e){"use strict"
8479
8479
  Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
@@ -9522,4 +9522,4 @@ e.default=class{constructor(e){if(this._data=new t.default,e)for(let t=0;t<e.len
9522
9522
  return this}get(e){let t=this._data[e]
9523
9523
  return t===r.UNDEFINED_KEY?void 0:t}set(e,t){return this._data[e]=t,this}delete(e){return this._data[e]=r.UNDEFINED_KEY,!0}}}))
9524
9524
 
9525
- //# sourceMappingURL=vendor-cd719f773d30a657813d1167126edfeb.map
9525
+ //# sourceMappingURL=vendor-ae0ef37383c371db894ddba69e9dfe7c.map
@@ -8,7 +8,7 @@
8
8
  <title>Ghost Admin</title>
9
9
 
10
10
 
11
- <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%225.116%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%2270b6e1c5ab%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%22ba6e7c2c75%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%221f15c97ca4%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%227fa3fe34af%22%2C%22postsFilename%22%3A%22posts.js%22%2C%22postsHash%22%3A%227ad9127d68%22%2C%22statsFilename%22%3A%22stats.js%22%2C%22statsHash%22%3A%22745f9f9556%22%2C%22adminXActivitypubCustomUrl%22%3A%22https%3A%2F%2Fcdn.jsdelivr.net%2Fghost%2Fadmin-x-activitypub%400%2Fdist%2Fadmin-x-activitypub.js%22%7D" />
11
+ <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%225.116%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%2270b6e1c5ab%22%2C%22adminXDemoFilename%22%3A%22admin-x-demo.js%22%2C%22adminXDemoHash%22%3A%22fd54878445%22%2C%22adminXSettingsFilename%22%3A%22admin-x-settings.js%22%2C%22adminXSettingsHash%22%3A%22f374d17369%22%2C%22adminXActivitypubFilename%22%3A%22admin-x-activitypub.js%22%2C%22adminXActivitypubHash%22%3A%22bff4438287%22%2C%22postsFilename%22%3A%22posts.js%22%2C%22postsHash%22%3A%222c1461dad3%22%2C%22statsFilename%22%3A%22stats.js%22%2C%22statsHash%22%3A%22ffcc9f090c%22%2C%22adminXActivitypubCustomUrl%22%3A%22https%3A%2F%2Fcdn.jsdelivr.net%2Fghost%2Fadmin-x-activitypub%400%2Fdist%2Fadmin-x-activitypub.js%22%7D" />
12
12
 
13
13
  <meta name="HandheldFriendly" content="True" />
14
14
  <meta name="MobileOptimized" content="320" />
@@ -56,9 +56,9 @@
56
56
 
57
57
  <div id="ember-basic-dropdown-wormhole"></div>
58
58
 
59
- <script src="assets/vendor-72026232b36d97babc6320917c16c321.js"></script>
60
- <script src="assets/chunk.713.e9027c0cc3c56110f5da.js"></script>
61
- <script src="assets/chunk.524.8371443ef8f60db429d0.js"></script>
62
- <script src="assets/ghost-03b64c086f3c60cabc85fe7a7e2b640a.js"></script>
59
+ <script src="assets/vendor-8e3ee8261528bb429cfe78ce79a4a82a.js"></script>
60
+ <script src="assets/chunk.713.761d11035fe0bf3e557c.js"></script>
61
+ <script src="assets/chunk.524.578de86e5014b911b05a.js"></script>
62
+ <script src="assets/ghost-868c537d5c02ca65323d0122596a67ec.js"></script>
63
63
  </body>
64
64
  </html>
@@ -156,11 +156,15 @@ function getTinybirdTrackerScript(dataRoot) {
156
156
  return '';
157
157
  }
158
158
 
159
- const src = getAssetUrl('public/ghost-stats.js');
159
+ const src = getAssetUrl('public/ghost-stats.js', false);
160
160
 
161
- const endpoint = config.get('tinybird:tracker:endpoint');
162
- const token = config.get('tinybird:tracker:token');
163
- const datasource = config.get('tinybird:tracker:datasource');
161
+ const statsConfig = config.get('tinybird:tracker');
162
+ const localConfig = config.get('tinybird:tracker:local');
163
+ const localEnabled = localConfig?.enabled ?? false;
164
+
165
+ const endpoint = localEnabled ? localConfig.endpoint : statsConfig.endpoint;
166
+ const token = localEnabled ? localConfig.token : statsConfig.token;
167
+ const datasource = localEnabled ? localConfig.datasource : statsConfig.datasource;
164
168
 
165
169
  const tbParams = _.map({
166
170
  site_uuid: config.get('tinybird:tracker:id'),
@@ -360,7 +364,7 @@ module.exports = async function ghost_head(options) { // eslint-disable-line cam
360
364
  head.push(tagCodeInjection);
361
365
  }
362
366
 
363
- if (config.get('tinybird') && config.get('tinybird:tracker') && config.get('tinybird:tracker:scriptUrl')) {
367
+ if (config.get('tinybird') && config.get('tinybird:tracker')) {
364
368
  head.push(getTinybirdTrackerScript(dataRoot));
365
369
  }
366
370
 
@@ -3,11 +3,10 @@
3
3
  const STORAGE_KEY = 'session-id'
4
4
  let DATASOURCE = 'analytics_events'
5
5
  const storageMethods = {
6
- cookie: 'cookie',
7
6
  localStorage: 'localStorage',
8
7
  sessionStorage: 'sessionStorage',
9
8
  }
10
- let STORAGE_METHOD = storageMethods.cookie
9
+ let STORAGE_METHOD = storageMethods.localStorage
11
10
  let globalAttributes = {}
12
11
  let stringifyPayload = true
13
12
 
@@ -40,64 +39,37 @@
40
39
  )
41
40
  }
42
41
 
43
- function _getSessionIdFromCookie() {
44
- let cookie = {}
45
- document.cookie.split(';').forEach(function (el) {
46
- let [key, value] = el.split('=')
47
- cookie[key.trim()] = value
48
- })
49
- return cookie[STORAGE_KEY]
50
- }
51
-
52
42
  function _getSessionId() {
53
- if (
54
- [storageMethods.localStorage, storageMethods.sessionStorage].includes(
55
- STORAGE_METHOD
56
- )
57
- ) {
58
- const storage =
59
- STORAGE_METHOD === storageMethods.localStorage
60
- ? localStorage
61
- : sessionStorage
62
- const serializedItem = storage.getItem(STORAGE_KEY)
63
-
64
- if (!serializedItem) {
65
- return null
66
- }
67
-
68
- let item = null;
69
-
70
- try {
71
- item = JSON.parse(serializedItem)
72
- } catch (error) {
73
- return null
74
- }
75
-
76
- if(typeof item !== 'object' || item === null) {
77
- return null
78
- }
79
-
80
- const now = new Date()
43
+ const storage =
44
+ STORAGE_METHOD === storageMethods.localStorage
45
+ ? localStorage
46
+ : sessionStorage
47
+ const serializedItem = storage.getItem(STORAGE_KEY)
48
+
49
+ if (!serializedItem) {
50
+ return null
51
+ }
81
52
 
82
- if (now.getTime() > item.expiry) {
83
- storage.removeItem(STORAGE_KEY)
84
- return null
85
- }
53
+ let item = null;
86
54
 
87
- return item.value
55
+ try {
56
+ item = JSON.parse(serializedItem)
57
+ } catch (error) {
58
+ return null
88
59
  }
89
60
 
90
- return _getSessionIdFromCookie()
91
- }
61
+ if(typeof item !== 'object' || item === null) {
62
+ return null
63
+ }
92
64
 
93
- function _setSessionIdFromCookie(sessionId) {
94
- let cookieValue = `${STORAGE_KEY}=${sessionId}; Max-Age=1800; path=/; secure`
65
+ const now = new Date()
95
66
 
96
- if (domain) {
97
- cookieValue += `; domain=${domain}`
67
+ if (now.getTime() > item.expiry) {
68
+ storage.removeItem(STORAGE_KEY)
69
+ return null
98
70
  }
99
71
 
100
- document.cookie = cookieValue
72
+ return item.value
101
73
  }
102
74
 
103
75
  function _setSessionId() {
@@ -108,25 +80,17 @@
108
80
  */
109
81
 
110
82
  const sessionId = _getSessionId() || _uuidv4()
111
- if (
112
- [storageMethods.localStorage, storageMethods.sessionStorage].includes(
113
- STORAGE_METHOD
114
- )
115
- ) {
116
- const now = new Date()
117
- const item = {
118
- value: sessionId,
119
- expiry: now.getTime() + 14400 * 1000, // 4 hours
120
- }
121
- const value = JSON.stringify(item)
122
- const storage =
123
- STORAGE_METHOD === storageMethods.localStorage
124
- ? localStorage
125
- : sessionStorage
126
- return STORAGE_METHOD === storage.setItem(STORAGE_KEY, value)
83
+ const now = new Date()
84
+ const item = {
85
+ value: sessionId,
86
+ expiry: now.getTime() + 14400 * 1000, // 4 hours
127
87
  }
128
-
129
- return _setSessionIdFromCookie(sessionId)
88
+ const value = JSON.stringify(item)
89
+ const storage =
90
+ STORAGE_METHOD === storageMethods.localStorage
91
+ ? localStorage
92
+ : sessionStorage
93
+ storage.setItem(STORAGE_KEY, value)
130
94
  }
131
95
 
132
96
  /**
@@ -176,11 +140,11 @@
176
140
  *
177
141
  * @param { string } name Event name
178
142
  * @param { object } payload Event payload
179
- * @return { object } request response
143
+ * @return { Promise<any> } request response
180
144
  */
181
145
  async function _sendEvent(name, payload) {
182
146
  _setSessionId()
183
- const url = `https://e.ghost.org/tb/web_analytics?name=${DATASOURCE}&token=${token}`
147
+ const url = `${host}?name=${DATASOURCE}&token=${token}`
184
148
 
185
149
  let processedPayload
186
150
  if (stringifyPayload) {
@@ -240,14 +204,14 @@
240
204
  'user-agent': window.navigator.userAgent,
241
205
  locale,
242
206
  location: country,
243
- referrer: getReferrer(),
207
+ referrer: _getReferrer(),
244
208
  pathname: window.location.pathname,
245
209
  href: window.location.href,
246
210
  })
247
211
  }, 300)
248
212
  }
249
213
 
250
- function getReferrer() {
214
+ function _getReferrer() {
251
215
  // Fetch referrer data from query params - priority is the following order: ref, source, utm_source, utm_medium, referrer
252
216
  let refParam;
253
217
  let sourceParam;
@@ -301,7 +265,10 @@
301
265
  }
302
266
 
303
267
  // Client
304
- window.Tinybird = { trackEvent: _sendEvent }
268
+ window.Tinybird = {
269
+ trackEvent: _sendEvent,
270
+ _trackPageHit: _trackPageHit
271
+ }
305
272
 
306
273
  // Event listener
307
274
  window.addEventListener('hashchange', _trackPageHit)
@@ -0,0 +1,23 @@
1
+
2
+
3
+ SCHEMA >
4
+ `site_uuid` LowCardinality(String),
5
+ `timestamp` DateTime,
6
+ `action` LowCardinality(String),
7
+ `version` LowCardinality(String),
8
+ `session_id` String,
9
+ `member_uuid` String,
10
+ `member_status` String,
11
+ `post_uuid` String,
12
+ `post_type` String,
13
+ `location` String,
14
+ `source` String,
15
+ `pathname` String,
16
+ `href` String,
17
+ `device` String,
18
+ `os` String,
19
+ `browser` String
20
+
21
+ ENGINE "MergeTree"
22
+ ENGINE_PARTITION_KEY "toYYYYMM(timestamp)"
23
+ ENGINE_SORTING_KEY "site_uuid, timestamp, session_id"
@@ -0,0 +1,14 @@
1
+ TOKEN "tracker" APPEND
2
+
3
+
4
+ SCHEMA >
5
+ `timestamp` DateTime `json:$.timestamp`,
6
+ `session_id` String `json:$.session_id`,
7
+ `action` LowCardinality(String) `json:$.action`,
8
+ `version` LowCardinality(String) `json:$.version`,
9
+ `payload` JSON(max_dynamic_types=4, max_dynamic_paths=32) `json:$.payload`,
10
+ `site_uuid` LowCardinality(String) `json:$.payload.site_uuid`
11
+
12
+ ENGINE "MergeTree"
13
+ ENGINE_PARTITION_KEY "toYYYYMM(timestamp)"
14
+ ENGINE_SORTING_KEY "site_uuid, timestamp"
@@ -0,0 +1,161 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE timeseries
4
+ SQL >
5
+
6
+ %
7
+ {% set _single_day = defined(date_from) and day_diff(date_from, date_to) == 0 %}
8
+ with
9
+ {% if defined(date_from) %}
10
+ toStartOfDay(
11
+ toDate(
12
+ {{
13
+ Date(
14
+ date_from,
15
+ description="Starting day for filtering a date range",
16
+ required=False,
17
+ )
18
+ }}
19
+ )
20
+ ) as start,
21
+ {% else %} toStartOfDay(timestampAdd(today(), interval -7 day)) as start,
22
+ {% end %}
23
+ {% if defined(date_to) %}
24
+ toStartOfDay(
25
+ toDate(
26
+ {{
27
+ Date(
28
+ date_to,
29
+ description="Finishing day for filtering a date range",
30
+ required=False,
31
+ )
32
+ }}
33
+ )
34
+ ) as end
35
+ {% else %} toStartOfDay(today()) as end
36
+ {% end %}
37
+ {% if _single_day %}
38
+ select
39
+ arrayJoin(
40
+ arrayMap(
41
+ x -> toDateTime(toString(toDateTime(x)), {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}),
42
+ range(
43
+ toUInt32(toDateTime(start)), toUInt32(timestampAdd(end, interval 1 day)), 3600
44
+ )
45
+ )
46
+ ) as date
47
+ {% else %}
48
+ select
49
+ arrayJoin(
50
+ arrayMap(
51
+ x -> toDate(x),
52
+ range(toUInt32(start), toUInt32(timestampAdd(end, interval 1 day)), 24 * 3600)
53
+ )
54
+ ) as date
55
+ {% end %}
56
+
57
+
58
+ NODE session_metrics
59
+ DESCRIPTION >
60
+ Calculate session-level metrics (visits, pageviews, bounce rate, avg session duration)
61
+
62
+ SQL >
63
+
64
+ %
65
+ select
66
+ site_uuid,
67
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
68
+ toStartOfHour(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) as date,
69
+ {% else %}
70
+ toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) as date,
71
+ {% end %}
72
+ session_id,
73
+ pageviews,
74
+ is_bounce,
75
+ duration as session_sec
76
+ from mv_session_data sd
77
+ inner join filtered_sessions fs
78
+ on fs.session_id = sd.session_id
79
+ where
80
+ site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
81
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
82
+ and toDate(toTimezone(first_pageview, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) = {{ Date(date_from) }}
83
+ {% else %}
84
+ {% 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 %}
85
+ {% 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 %}
86
+ {% end %}
87
+
88
+
89
+ NODE data
90
+ DESCRIPTION >
91
+ Calculate KPIs per time period
92
+
93
+ SQL >
94
+
95
+ select
96
+ a.date,
97
+ uniq(distinct s.session_id) as visits,
98
+ sum(s.pageviews) as pageviews,
99
+ truncate(avg(s.is_bounce), 2) as bounce_rate,
100
+ truncate(avg(s.session_sec), 2) as avg_session_sec
101
+ from timeseries a
102
+ inner join session_metrics s on a.date = s.date
103
+ group by a.date
104
+ order by a.date
105
+
106
+
107
+ NODE pathname_pageviews
108
+ DESCRIPTION >
109
+ Calculate pageviews for specific pathname with time granularity handling
110
+
111
+ SQL >
112
+
113
+ %
114
+ select
115
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
116
+ toStartOfHour(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) as date,
117
+ {% else %}
118
+ toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) as date,
119
+ {% end %}
120
+ count() pageviews
121
+ from timeseries a
122
+ inner join _mv_hits h on
123
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
124
+ a.date = toStartOfHour(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
125
+ {% else %}
126
+ a.date = toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
127
+ {% end %}
128
+ where
129
+ site_uuid = {{ String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True) }}
130
+ {% if defined(date_from) and day_diff(date_from, date_to) == 0 %}
131
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) = {{ Date(date_from) }}
132
+ {% else %}
133
+ {% if defined(date_from) %} and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= {{ Date(date_from) }} {% else %} and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}})) >= timestampAdd(today(), interval -7 day) {% end %}
134
+ {% 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 %}
135
+ {% end %}
136
+ {% if defined(member_status) %} and member_status IN {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }} {% end %}
137
+ {% if defined(device) %} and device = {{ String(device, description="Device to filter on", required=False) }} {% end %}
138
+ {% if defined(browser) %} and browser = {{ String(browser, description="Browser to filter on", required=False) }} {% end %}
139
+ {% if defined(os) %} and os = {{ String(os, description="Operating system to filter on", required=False) }} {% end %}
140
+ {% if defined(source) %} and source = {{ String(source, description="Source to filter on", required=False) }} {% end %}
141
+ {% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
142
+ {% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
143
+ group by date
144
+ order by date
145
+
146
+
147
+ NODE finished_data
148
+ SQL >
149
+
150
+ %
151
+ select
152
+ a.date as date,
153
+ coalesce(b.visits, 0) as visits,
154
+ {% if defined(pathname) %}coalesce(c.pageviews, 0){% else %}coalesce(b.pageviews, 0){% end %} as pageviews,
155
+ coalesce(b.bounce_rate, 0) as bounce_rate,
156
+ coalesce(b.avg_session_sec, 0) as avg_session_sec
157
+ from timeseries a
158
+ left join data b on a.date = b.date
159
+ {% if defined(pathname) %}left join pathname_pageviews c on a.date = c.date{% end %}
160
+
161
+ TYPE ENDPOINT
@@ -0,0 +1,52 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE _top_browsers_0
4
+ SQL >
5
+
6
+ %
7
+ select
8
+ browser,
9
+ uniqExact(session_id) as visits
10
+ from _mv_hits h
11
+ inner join filtered_sessions fs
12
+ on fs.session_id = h.session_id
13
+ where
14
+ site_uuid = {{String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True)}}
15
+ {% if defined(date_from) %}
16
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
17
+ >=
18
+ {{ Date(date_from, description="Starting day for filtering a date range", required=False) }}
19
+ {% else %}
20
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
21
+ >=
22
+ timestampAdd(today(), interval -7 day)
23
+ {% end %}
24
+ {% if defined(date_to) %}
25
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
26
+ <=
27
+ {{ Date(date_to, description="Finishing day for filtering a date range", required=False) }}
28
+ {% else %}
29
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
30
+ <=
31
+ today()
32
+ {% end %}
33
+ {% if defined(member_status) %}
34
+ and member_status IN (
35
+ select arrayJoin(
36
+ {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
37
+ || if('paid' IN {{ Array(member_status) }}, ['comped'], [])
38
+ )
39
+ )
40
+ {% end %}
41
+ {% if defined(device) %} and device = {{ String(device, description="Device to filter on", required=False) }} {% end %}
42
+ {% if defined(browser) %} and browser = {{ String(browser, description="Browser to filter on", required=False) }} {% end %}
43
+ {% if defined(os) %} and os = {{ String(os, description="Operating system to filter on", required=False) }} {% end %}
44
+ -- added source filter back
45
+ {% if defined(source) %} and source = {{ String(source, description="Source to filter on", required=False) }} {% end %}
46
+ {% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
47
+ {% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
48
+ group by browser
49
+ order by visits desc
50
+ limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }}
51
+
52
+ TYPE ENDPOINT
@@ -0,0 +1,51 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE _top_devices_0
4
+ SQL >
5
+
6
+ %
7
+ select
8
+ device,
9
+ uniqExact(session_id) as visits
10
+ from _mv_hits h
11
+ inner join filtered_sessions fs
12
+ on fs.session_id = h.session_id
13
+ where
14
+ site_uuid = {{String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True)}}
15
+ {% if defined(date_from) %}
16
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
17
+ >=
18
+ {{ Date(date_from, description="Starting day for filtering a date range", required=False) }}
19
+ {% else %}
20
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
21
+ >=
22
+ timestampAdd(today(), interval -7 day)
23
+ {% end %}
24
+ {% if defined(date_to) %}
25
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
26
+ <=
27
+ {{ Date(date_to, description="Finishing day for filtering a date range", required=False) }}
28
+ {% else %}
29
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
30
+ <=
31
+ today()
32
+ {% end %}
33
+ {% if defined(member_status) %}
34
+ and member_status IN (
35
+ select arrayJoin(
36
+ {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
37
+ || if('paid' IN {{ Array(member_status) }}, ['comped'], [])
38
+ )
39
+ )
40
+ {% end %}
41
+ {% if defined(device) %} and device = {{ String(device, description="Device to filter on", required=False) }} {% end %}
42
+ {% if defined(browser) %} and browser = {{ String(browser, description="Browser to filter on", required=False) }} {% end %}
43
+ {% if defined(os) %} and os = {{ String(os, description="Operating system to filter on", required=False) }} {% end %}
44
+ {% if defined(source) %} and source = {{ String(source, description="Source to filter on", required=False) }} {% end %}
45
+ {% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
46
+ {% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
47
+ group by device
48
+ order by visits desc
49
+ limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }}
50
+
51
+ TYPE ENDPOINT
@@ -0,0 +1,51 @@
1
+ TOKEN "stats_page" READ
2
+
3
+ NODE _top_locations_0
4
+ SQL >
5
+
6
+ %
7
+ select
8
+ location,
9
+ uniqExact(session_id) as visits
10
+ from _mv_hits h
11
+ inner join filtered_sessions fs
12
+ on fs.session_id = h.session_id
13
+ where
14
+ site_uuid = {{String(site_uuid, 'mock_site_uuid', description="Tenant ID", required=True)}}
15
+ {% if defined(date_from) %}
16
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
17
+ >=
18
+ {{ Date(date_from, description="Starting day for filtering a date range", required=False) }}
19
+ {% else %}
20
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
21
+ >=
22
+ timestampAdd(today(), interval -7 day)
23
+ {% end %}
24
+ {% if defined(date_to) %}
25
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
26
+ <=
27
+ {{ Date(date_to, description="Finishing day for filtering a date range", required=False) }}
28
+ {% else %}
29
+ and toDate(toTimezone(timestamp, {{String(timezone, 'Etc/UTC', description="Site timezone", required=True)}}))
30
+ <=
31
+ today()
32
+ {% end %}
33
+ {% if defined(member_status) %}
34
+ and member_status IN (
35
+ select arrayJoin(
36
+ {{ Array(member_status, "'undefined', 'free', 'paid'", description="Member status to filter on", required=False) }}
37
+ || if('paid' IN {{ Array(member_status) }}, ['comped'], [])
38
+ )
39
+ )
40
+ {% end %}
41
+ {% if defined(device) %} and device = {{ String(device, description="Device to filter on", required=False) }} {% end %}
42
+ {% if defined(browser) %} and browser = {{ String(browser, description="Browser to filter on", required=False) }} {% end %}
43
+ {% if defined(os) %} and os = {{ String(os, description="Operating system to filter on", required=False) }} {% end %}
44
+ {% if defined(source) %} and source = {{ String(source, description="Source to filter on", required=False) }} {% end %}
45
+ {% if defined(location) %} and location = {{ String(location, description="Location to filter on", required=False) }} {% end %}
46
+ {% if defined(pathname) %} and pathname = {{ String(pathname, description="Pathname to filter on", required=False) }} {% end %}
47
+ group by location
48
+ order by visits desc
49
+ limit {{ Int32(skip, 0) }},{{ Int32(limit, 50) }}
50
+
51
+ TYPE ENDPOINT