@huloglobal/vendure-plugin-visitor-analytics 0.4.3 → 0.6.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.
@@ -0,0 +1,12 @@
1
+ import { RequestContext, TransactionalConnection } from '@vendure/core';
2
+ export declare const visitorAnalyticsAdminApiSchema: import("graphql").DocumentNode;
3
+ export declare class VisitorAnalyticsAdminResolver {
4
+ private connection;
5
+ constructor(connection: TransactionalConnection);
6
+ huloVisitorSummary(ctx: RequestContext, channelId?: number, daysInput?: number): Promise<any>;
7
+ huloVisitorSources(channelId?: number, daysInput?: number): Promise<any[]>;
8
+ huloVisitorTopPages(channelId?: number, daysInput?: number): Promise<any[]>;
9
+ huloVisitorFunnel(input: any): Promise<any>;
10
+ huloVisitorJourney(visitorId: string): Promise<any[]>;
11
+ }
12
+ //# sourceMappingURL=admin-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-api.d.ts","sourceRoot":"","sources":["../src/admin-api.ts"],"names":[],"mappings":"AAYA,OAAO,EAA0B,cAAc,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAEhG,eAAO,MAAM,8BAA8B,gCAsE1C,CAAC;AAUF,qBAEa,6BAA6B;IAC1B,OAAO,CAAC,UAAU;gBAAV,UAAU,EAAE,uBAAuB;IAIjD,kBAAkB,CACb,GAAG,EAAE,cAAc,EACP,SAAS,CAAC,EAAE,MAAM,EACvB,SAAS,CAAC,EAAE,MAAM,GACjC,OAAO,CAAC,GAAG,CAAC;IAsCT,kBAAkB,CAAoB,SAAS,CAAC,EAAE,MAAM,EAAgB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAqB3G,mBAAmB,CAAoB,SAAS,CAAC,EAAE,MAAM,EAAgB,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IA0B5G,iBAAiB,CAAgB,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IA8B1D,kBAAkB,CAAoB,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;CAajF"}
@@ -0,0 +1,264 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.VisitorAnalyticsAdminResolver = exports.visitorAnalyticsAdminApiSchema = void 0;
16
+ /**
17
+ * Vendure Admin API extensions for HULO Visitor Analytics.
18
+ *
19
+ * Mirrors the operator queries from the REST controller — summary,
20
+ * sources, top-pages, funnel, journey — so any GraphQL client can
21
+ * drive the dashboards. The high-frequency public path POST /ees/track
22
+ * stays REST: it's an anonymous beacon, ingests potentially millions
23
+ * of events / day, and benefits from being outside the resolver stack.
24
+ */
25
+ const common_1 = require("@nestjs/common");
26
+ const graphql_1 = require("@nestjs/graphql");
27
+ const graphql_tag_1 = require("graphql-tag");
28
+ const core_1 = require("@vendure/core");
29
+ exports.visitorAnalyticsAdminApiSchema = (0, graphql_tag_1.gql) `
30
+ type HuloVisitorSummary {
31
+ days: Int!
32
+ channelId: Int
33
+ visitors: Int!
34
+ sessions: Int!
35
+ pageViews: Int!
36
+ events: Int!
37
+ bounceRate: Float!
38
+ avgSessionSec: Float!
39
+ }
40
+
41
+ type HuloVisitorSource {
42
+ source: String!
43
+ visitors: Int!
44
+ sessions: Int!
45
+ }
46
+
47
+ type HuloVisitorPage {
48
+ url: String!
49
+ title: String
50
+ views: Int!
51
+ uniqueVisitors: Int!
52
+ avgTimeOnPageSec: Float!
53
+ }
54
+
55
+ type HuloFunnelStep {
56
+ index: Int!
57
+ urlPattern: String!
58
+ label: String
59
+ users: Int!
60
+ dropOffPct: Float!
61
+ }
62
+
63
+ type HuloVisitorFunnel {
64
+ days: Int!
65
+ steps: [HuloFunnelStep!]!
66
+ }
67
+
68
+ type HuloVisitorEvent {
69
+ id: ID!
70
+ createdAt: DateTime!
71
+ type: String!
72
+ url: String
73
+ title: String
74
+ referrerDomain: String
75
+ country: String
76
+ region: String
77
+ city: String
78
+ browser: String
79
+ os: String
80
+ device: String
81
+ sessionId: String!
82
+ visitorId: String!
83
+ customerId: Int
84
+ }
85
+
86
+ input HuloVisitorFunnelInput {
87
+ channelId: Int
88
+ days: Int
89
+ steps: [String!]!
90
+ }
91
+
92
+ extend type Query {
93
+ huloVisitorSummary(channelId: Int, days: Int): HuloVisitorSummary!
94
+ huloVisitorSources(channelId: Int, days: Int): [HuloVisitorSource!]!
95
+ huloVisitorTopPages(channelId: Int, days: Int): [HuloVisitorPage!]!
96
+ huloVisitorFunnel(input: HuloVisitorFunnelInput!): HuloVisitorFunnel!
97
+ huloVisitorJourney(visitorId: String!): [HuloVisitorEvent!]!
98
+ }
99
+ `;
100
+ function clampDays(input) {
101
+ return Math.min(Math.max(Number(input) || 7, 1), 365);
102
+ }
103
+ function channelFilter(channelId) {
104
+ if (channelId)
105
+ return { where: ' AND channelId = ?', params: [channelId] };
106
+ return { where: '', params: [] };
107
+ }
108
+ let VisitorAnalyticsAdminResolver = class VisitorAnalyticsAdminResolver {
109
+ constructor(connection) {
110
+ this.connection = connection;
111
+ }
112
+ async huloVisitorSummary(ctx, channelId, daysInput) {
113
+ const days = clampDays(daysInput);
114
+ const c = channelFilter(channelId);
115
+ const totals = await this.connection.rawConnection.query(`SELECT COUNT(DISTINCT visitorId) AS visitors,
116
+ COUNT(DISTINCT sessionId) AS sessions,
117
+ SUM(type = 'pageview') AS pageViews,
118
+ COUNT(*) AS events
119
+ FROM visitor_event
120
+ WHERE createdAt >= DATE_SUB(NOW(), INTERVAL ? DAY)${c.where}`, [days, ...c.params]);
121
+ const t = totals[0] || {};
122
+ const sessionRows = await this.connection.rawConnection.query(`SELECT sessionId,
123
+ TIMESTAMPDIFF(SECOND, MIN(createdAt), MAX(createdAt)) AS dur,
124
+ COUNT(*) AS n
125
+ FROM visitor_event
126
+ WHERE createdAt >= DATE_SUB(NOW(), INTERVAL ? DAY)${c.where}
127
+ GROUP BY sessionId`, [days, ...c.params]);
128
+ const ssRows = sessionRows;
129
+ const bounces = ssRows.filter((s) => Number(s.n) <= 1).length;
130
+ const avg = ssRows.length ? ssRows.reduce((a, s) => a + Number(s.dur || 0), 0) / ssRows.length : 0;
131
+ return {
132
+ days, channelId: channelId || null,
133
+ visitors: Number(t.visitors) || 0,
134
+ sessions: Number(t.sessions) || 0,
135
+ pageViews: Number(t.pageViews) || 0,
136
+ events: Number(t.events) || 0,
137
+ bounceRate: ssRows.length ? bounces / ssRows.length : 0,
138
+ avgSessionSec: avg,
139
+ };
140
+ }
141
+ async huloVisitorSources(channelId, daysInput) {
142
+ const days = clampDays(daysInput);
143
+ const c = channelFilter(channelId);
144
+ const rows = await this.connection.rawConnection.query(`SELECT COALESCE(NULLIF(referrerDomain, ''), '(direct)') AS source,
145
+ COUNT(DISTINCT visitorId) AS visitors,
146
+ COUNT(DISTINCT sessionId) AS sessions
147
+ FROM visitor_event
148
+ WHERE createdAt >= DATE_SUB(NOW(), INTERVAL ? DAY)${c.where}
149
+ GROUP BY source ORDER BY sessions DESC LIMIT 50`, [days, ...c.params]);
150
+ return rows.map((r) => ({
151
+ source: r.source,
152
+ visitors: Number(r.visitors) || 0,
153
+ sessions: Number(r.sessions) || 0,
154
+ }));
155
+ }
156
+ async huloVisitorTopPages(channelId, daysInput) {
157
+ const days = clampDays(daysInput);
158
+ const c = channelFilter(channelId);
159
+ const rows = await this.connection.rawConnection.query(`SELECT url,
160
+ MAX(title) AS title,
161
+ COUNT(*) AS views,
162
+ COUNT(DISTINCT visitorId) AS uniqueVisitors,
163
+ AVG(COALESCE(timeOnPageMs, 0)) / 1000 AS avgTimeOnPageSec
164
+ FROM visitor_event
165
+ WHERE type = 'pageview'
166
+ AND createdAt >= DATE_SUB(NOW(), INTERVAL ? DAY)${c.where}
167
+ GROUP BY url ORDER BY views DESC LIMIT 50`, [days, ...c.params]);
168
+ return rows.map((r) => ({
169
+ url: r.url || '',
170
+ title: r.title || null,
171
+ views: Number(r.views) || 0,
172
+ uniqueVisitors: Number(r.uniqueVisitors) || 0,
173
+ avgTimeOnPageSec: Number(r.avgTimeOnPageSec) || 0,
174
+ }));
175
+ }
176
+ async huloVisitorFunnel(input) {
177
+ var _a;
178
+ const days = clampDays(input === null || input === void 0 ? void 0 : input.days);
179
+ const c = channelFilter(input === null || input === void 0 ? void 0 : input.channelId);
180
+ const steps = Array.isArray(input === null || input === void 0 ? void 0 : input.steps) ? input.steps.map(String) : [];
181
+ if (!steps.length)
182
+ return { days, steps: [] };
183
+ // For each step, count distinct visitors who hit it. This is a
184
+ // pageview-funnel approximation; ordered funnel (visitor must
185
+ // have hit step i-1 before i) is a future enhancement.
186
+ const out = [];
187
+ let prevUsers = null;
188
+ for (let i = 0; i < steps.length; i++) {
189
+ const pattern = steps[i];
190
+ const rows = await this.connection.rawConnection.query(`SELECT COUNT(DISTINCT visitorId) AS n
191
+ FROM visitor_event
192
+ WHERE type = 'pageview'
193
+ AND url LIKE ?
194
+ AND createdAt >= DATE_SUB(NOW(), INTERVAL ? DAY)${c.where}`, [pattern.replace(/\*/g, '%'), days, ...c.params]);
195
+ const users = Number((_a = rows[0]) === null || _a === void 0 ? void 0 : _a.n) || 0;
196
+ const dropOff = prevUsers && prevUsers > 0 ? 1 - (users / prevUsers) : 0;
197
+ out.push({ index: i, urlPattern: pattern, label: null, users, dropOffPct: dropOff });
198
+ prevUsers = users;
199
+ }
200
+ return { days, steps: out };
201
+ }
202
+ async huloVisitorJourney(visitorId) {
203
+ if (!visitorId)
204
+ return [];
205
+ const rows = await this.connection.rawConnection.query(`SELECT id, createdAt, type, url, title, referrerDomain,
206
+ country, region, city, browser, os, device,
207
+ sessionId, visitorId, customerId
208
+ FROM visitor_event
209
+ WHERE visitorId = ?
210
+ ORDER BY createdAt ASC LIMIT 1000`, [String(visitorId)]);
211
+ return rows;
212
+ }
213
+ };
214
+ exports.VisitorAnalyticsAdminResolver = VisitorAnalyticsAdminResolver;
215
+ __decorate([
216
+ (0, graphql_1.Query)(),
217
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
218
+ __param(0, (0, core_1.Ctx)()),
219
+ __param(1, (0, graphql_1.Args)('channelId')),
220
+ __param(2, (0, graphql_1.Args)('days')),
221
+ __metadata("design:type", Function),
222
+ __metadata("design:paramtypes", [core_1.RequestContext, Number, Number]),
223
+ __metadata("design:returntype", Promise)
224
+ ], VisitorAnalyticsAdminResolver.prototype, "huloVisitorSummary", null);
225
+ __decorate([
226
+ (0, graphql_1.Query)(),
227
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
228
+ __param(0, (0, graphql_1.Args)('channelId')),
229
+ __param(1, (0, graphql_1.Args)('days')),
230
+ __metadata("design:type", Function),
231
+ __metadata("design:paramtypes", [Number, Number]),
232
+ __metadata("design:returntype", Promise)
233
+ ], VisitorAnalyticsAdminResolver.prototype, "huloVisitorSources", null);
234
+ __decorate([
235
+ (0, graphql_1.Query)(),
236
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
237
+ __param(0, (0, graphql_1.Args)('channelId')),
238
+ __param(1, (0, graphql_1.Args)('days')),
239
+ __metadata("design:type", Function),
240
+ __metadata("design:paramtypes", [Number, Number]),
241
+ __metadata("design:returntype", Promise)
242
+ ], VisitorAnalyticsAdminResolver.prototype, "huloVisitorTopPages", null);
243
+ __decorate([
244
+ (0, graphql_1.Query)(),
245
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
246
+ __param(0, (0, graphql_1.Args)('input')),
247
+ __metadata("design:type", Function),
248
+ __metadata("design:paramtypes", [Object]),
249
+ __metadata("design:returntype", Promise)
250
+ ], VisitorAnalyticsAdminResolver.prototype, "huloVisitorFunnel", null);
251
+ __decorate([
252
+ (0, graphql_1.Query)(),
253
+ (0, core_1.Allow)(core_1.Permission.ReadCustomer),
254
+ __param(0, (0, graphql_1.Args)('visitorId')),
255
+ __metadata("design:type", Function),
256
+ __metadata("design:paramtypes", [String]),
257
+ __metadata("design:returntype", Promise)
258
+ ], VisitorAnalyticsAdminResolver.prototype, "huloVisitorJourney", null);
259
+ exports.VisitorAnalyticsAdminResolver = VisitorAnalyticsAdminResolver = __decorate([
260
+ (0, graphql_1.Resolver)(),
261
+ (0, common_1.Injectable)(),
262
+ __metadata("design:paramtypes", [core_1.TransactionalConnection])
263
+ ], VisitorAnalyticsAdminResolver);
264
+ //# sourceMappingURL=admin-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-api.js","sourceRoot":"","sources":["../src/admin-api.ts"],"names":[],"mappings":"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"}
package/dist/plugin.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Type } from '@vendure/core';
2
- import { RetentionOptions, UpdateChecker } from '@huloglobal/vendure-licence-sdk';
2
+ import { LicenceStatus, RetentionOptions, UpdateChecker } from '@huloglobal/vendure-licence-sdk';
3
3
  export interface VisitorAnalyticsPluginOptions {
4
4
  /** Public host of the Vendure server. Used in licence host-match. */
5
5
  publicBaseUrl: string;
@@ -56,9 +56,12 @@ export declare function getOptions(): typeof DEFAULT_OPTIONS & VisitorAnalyticsP
56
56
  export declare class VisitorAnalyticsPlugin {
57
57
  private static revocation;
58
58
  private static updateChecker;
59
+ private static heartbeat;
60
+ private static licenceStatus;
59
61
  static getUpdateChecker(): UpdateChecker | null;
60
62
  static getPackageVersion(): string;
61
63
  static getPackageName(): string;
64
+ static getLicenceStatus(): LicenceStatus | null;
62
65
  static init(options: VisitorAnalyticsPluginOptions): Type<VisitorAnalyticsPlugin>;
63
66
  static uiExtensions: {
64
67
  extensionPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,IAAI,EAAiB,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAqB,aAAa,EAAiB,MAAM,iCAAiC,CAAC;AAUpH,MAAM,WAAW,6BAA6B;IAC1C,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB;;;gDAG4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB;6EACyE;IACzE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;yEAEqE;IACrE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;qEAEiE;IACjE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;6CAEyC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,mDAAmD;IACnD,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD;;yEAEqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;2EAEuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAG9B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAgBD,QAAA,MAAM,eAAe,EAAE,6BAMtB,CAAC;AAGF,wBAAgB,UAAU,IAAI,OAAO,eAAe,GAAG,6BAA6B,CAEnF;AAED;;;;;;;;;;;GAWG;AACH,qBAOa,sBAAsB;IAC/B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAkC;IAC3D,OAAO,CAAC,MAAM,CAAC,aAAa,CAA8B;IAE1D,MAAM,CAAC,gBAAgB,IAAI,aAAa,GAAG,IAAI;IAC/C,MAAM,CAAC,iBAAiB,IAAI,MAAM;IAClC,MAAM,CAAC,cAAc,IAAI,MAAM;IAE/B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,6BAA6B,GAAG,IAAI,CAAC,sBAAsB,CAAC;IAiCjF,MAAM,CAAC,YAAY;;;;;;;;MAUjB;CACL"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,IAAI,EAAiB,MAAM,eAAe,CAAC;AACxE,OAAO,EAAmC,aAAa,EAAE,gBAAgB,EAAqB,aAAa,EAAiB,MAAM,iCAAiC,CAAC;AAWpK,MAAM,WAAW,6BAA6B;IAC1C,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB;;;gDAG4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB;6EACyE;IACzE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;yEAEqE;IACrE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;qEAEiE;IACjE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;6CAEyC;IACzC,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB,mDAAmD;IACnD,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD;;yEAEqE;IACrE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;2EAEuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAG9B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAgBD,QAAA,MAAM,eAAe,EAAE,6BAMtB,CAAC;AAGF,wBAAgB,UAAU,IAAI,OAAO,eAAe,GAAG,6BAA6B,CAEnF;AAED;;;;;;;;;;;GAWG;AACH,qBAWa,sBAAsB;IAC/B,OAAO,CAAC,MAAM,CAAC,UAAU,CAAkC;IAC3D,OAAO,CAAC,MAAM,CAAC,aAAa,CAA8B;IAC1D,OAAO,CAAC,MAAM,CAAC,SAAS,CAA0B;IAClD,OAAO,CAAC,MAAM,CAAC,aAAa,CAA8B;IAE1D,MAAM,CAAC,gBAAgB,IAAI,aAAa,GAAG,IAAI;IAC/C,MAAM,CAAC,iBAAiB,IAAI,MAAM;IAClC,MAAM,CAAC,cAAc,IAAI,MAAM;IAC/B,MAAM,CAAC,gBAAgB,IAAI,aAAa,GAAG,IAAI;IAE/C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,6BAA6B,GAAG,IAAI,CAAC,sBAAsB,CAAC;IA4CjF,MAAM,CAAC,YAAY;;;;;;;;MAUjB;CACL"}
package/dist/plugin.js CHANGED
@@ -14,6 +14,7 @@ const vendure_licence_sdk_1 = require("@huloglobal/vendure-licence-sdk");
14
14
  const conversion_goal_entity_1 = require("./conversion-goal.entity");
15
15
  const visitor_event_entity_1 = require("./visitor-event.entity");
16
16
  const visitor_tracking_service_1 = require("./visitor-tracking.service");
17
+ const admin_api_1 = require("./admin-api");
17
18
  const visitor_tracking_controller_1 = require("./visitor-tracking.controller");
18
19
  // eslint-disable-next-line @typescript-eslint/no-var-requires
19
20
  const PKG_VERSION = require('../package.json').version;
@@ -57,6 +58,7 @@ let VisitorAnalyticsPlugin = VisitorAnalyticsPlugin_1 = class VisitorAnalyticsPl
57
58
  static getUpdateChecker() { return VisitorAnalyticsPlugin_1.updateChecker; }
58
59
  static getPackageVersion() { return PKG_VERSION; }
59
60
  static getPackageName() { return PKG_NAME; }
61
+ static getLicenceStatus() { return VisitorAnalyticsPlugin_1.licenceStatus; }
60
62
  static init(options) {
61
63
  cachedOptions = options;
62
64
  if (!VisitorAnalyticsPlugin_1.revocation) {
@@ -76,10 +78,20 @@ let VisitorAnalyticsPlugin = VisitorAnalyticsPlugin_1 = class VisitorAnalyticsPl
76
78
  publicKey: HULO_PUBLIC_KEY,
77
79
  revokedIds: VisitorAnalyticsPlugin_1.revocation.getRevokedIds(),
78
80
  });
81
+ VisitorAnalyticsPlugin_1.licenceStatus = status;
79
82
  if (!status.valid) {
80
83
  // eslint-disable-next-line no-console
81
84
  console.warn(`[@huloglobal/vendure-plugin-visitor-analytics] ${status.message}` +
82
- ` — Running in unlicensed mode (ingest works, admin dashboards disabled). Purchase a key at https://elite-software.co.uk/licence/buy/${PLUGIN_ID}`);
85
+ ` — Running in FREE tier: 100 events/day cap, conversion goals disabled, live SSE feed disabled, CSV export disabled. Buy a licence at https://elite.charity/licence/buy/${PLUGIN_ID}`);
86
+ }
87
+ if (!VisitorAnalyticsPlugin_1.heartbeat) {
88
+ VisitorAnalyticsPlugin_1.heartbeat = new vendure_licence_sdk_1.Heartbeat({
89
+ packageName: PKG_NAME,
90
+ packageVersion: PKG_VERSION,
91
+ licenceKey: options.licenceKey,
92
+ publicKeyFingerprint: (0, vendure_licence_sdk_1.fingerprintPublicKey)(HULO_PUBLIC_KEY),
93
+ });
94
+ VisitorAnalyticsPlugin_1.heartbeat.start();
83
95
  }
84
96
  return VisitorAnalyticsPlugin_1;
85
97
  }
@@ -87,6 +99,8 @@ let VisitorAnalyticsPlugin = VisitorAnalyticsPlugin_1 = class VisitorAnalyticsPl
87
99
  exports.VisitorAnalyticsPlugin = VisitorAnalyticsPlugin;
88
100
  VisitorAnalyticsPlugin.revocation = null;
89
101
  VisitorAnalyticsPlugin.updateChecker = null;
102
+ VisitorAnalyticsPlugin.heartbeat = null;
103
+ VisitorAnalyticsPlugin.licenceStatus = null;
90
104
  VisitorAnalyticsPlugin.uiExtensions = {
91
105
  extensionPath: __dirname + '/../ui',
92
106
  ngModules: [
@@ -101,10 +115,14 @@ VisitorAnalyticsPlugin.uiExtensions = {
101
115
  exports.VisitorAnalyticsPlugin = VisitorAnalyticsPlugin = VisitorAnalyticsPlugin_1 = __decorate([
102
116
  (0, core_1.VendurePlugin)({
103
117
  imports: [core_1.PluginCommonModule],
104
- providers: [visitor_tracking_service_1.VisitorTrackingService],
118
+ providers: [visitor_tracking_service_1.VisitorTrackingService, admin_api_1.VisitorAnalyticsAdminResolver],
105
119
  controllers: [visitor_tracking_controller_1.VisitorTrackingController],
106
120
  entities: [visitor_event_entity_1.VisitorEvent, conversion_goal_entity_1.ConversionGoal],
107
121
  compatibility: '^3.0.0',
122
+ adminApiExtensions: {
123
+ schema: admin_api_1.visitorAnalyticsAdminApiSchema,
124
+ resolvers: [admin_api_1.VisitorAnalyticsAdminResolver],
125
+ },
108
126
  })
109
127
  ], VisitorAnalyticsPlugin);
110
128
  //# sourceMappingURL=plugin.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
@@ -56,7 +56,7 @@ export declare class VisitorTrackingController implements OnApplicationBootstrap
56
56
  * Each event payload:
57
57
  * data: { ts, activeCount, recent: [{ visitorId, url, country, secondsAgo }] }
58
58
  */
59
- live(ctx: RequestContext, req: Request, res: Response): Promise<void>;
59
+ live(ctx: RequestContext, req: Request, res: Response): Promise<Response<any, Record<string, any>> | undefined>;
60
60
  /** Journey timeline for one visitor — every event in order. */
61
61
  journey(ctx: RequestContext, visitorId: string, res: Response): Promise<Response<any, Record<string, any>> | undefined>;
62
62
  /** Recent visitors — paginated via take + skip. */
@@ -1 +1 @@
1
- {"version":3,"file":"visitor-tracking.controller.d.ts","sourceRoot":"","sources":["../src/visitor-tracking.controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"visitor-tracking.controller.d.ts","sourceRoot":"","sources":["../src/visitor-tracking.controller.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,35 @@ const COOKIE_VISITOR = 'ees_vid';
24
24
  const COOKIE_SESSION = 'ees_sid';
25
25
  const VISITOR_TTL_DAYS = 730; // ~2 years
26
26
  const SESSION_IDLE_MIN = 30; // 30-minute idle session timeout
27
+ /** Free-tier daily event cap. 100 / UTC day across the whole install
28
+ * — enough to evaluate, not enough to run a real store on. The
29
+ * counter is in-memory only (acceptable: free-tier installs aren't
30
+ * multi-instance anyway, and resetting on restart works in the
31
+ * customer's favour). */
32
+ const FREE_TIER_DAILY_CAP = 100;
33
+ const freeTierBudget = (() => {
34
+ let day = '';
35
+ let used = 0;
36
+ return {
37
+ consume(n) {
38
+ const today = new Date().toISOString().slice(0, 10);
39
+ if (today !== day) {
40
+ day = today;
41
+ used = 0;
42
+ }
43
+ if (used + n > FREE_TIER_DAILY_CAP)
44
+ return false;
45
+ used += n;
46
+ return true;
47
+ },
48
+ snapshot() {
49
+ const today = new Date().toISOString().slice(0, 10);
50
+ if (today !== day)
51
+ return { day: today, used: 0, cap: FREE_TIER_DAILY_CAP };
52
+ return { day, used, cap: FREE_TIER_DAILY_CAP };
53
+ },
54
+ };
55
+ })();
27
56
  function requireAdmin(ctx, res) {
28
57
  if (!(ctx === null || ctx === void 0 ? void 0 : ctx.activeUserId)) {
29
58
  res.status(401).json({ error: 'Authentication required' });
@@ -107,6 +136,15 @@ let VisitorTrackingController = class VisitorTrackingController {
107
136
  return res.status(204).end();
108
137
  if (this.rateLimited(req, res, 'track'))
109
138
  return;
139
+ // Tier-gate: unlicensed installs are capped at 100 events / UTC day.
140
+ // Once the cap is hit, /track returns 200 with `skipped: 'free-tier-cap'`
141
+ // so the storefront's beacon doesn't surface errors to end users.
142
+ if (!(0, vendure_licence_sdk_1.isLicensed)(plugin_1.VisitorAnalyticsPlugin.getLicenceStatus())) {
143
+ const eventsLen = Array.isArray((body || {}).events) ? body.events.length : 1;
144
+ if (!freeTierBudget.consume(eventsLen)) {
145
+ return res.json({ stored: 0, skipped: 'free-tier-cap', cap: FREE_TIER_DAILY_CAP });
146
+ }
147
+ }
110
148
  const opts = (0, plugin_1.getOptions)();
111
149
  // Privacy: honour Do-Not-Track when configured. We still return 200
112
150
  // so the storefront can't tell the difference between "stored" and
@@ -397,6 +435,9 @@ let VisitorTrackingController = class VisitorTrackingController {
397
435
  var _a;
398
436
  if (!requireAdmin(ctx, res))
399
437
  return;
438
+ if (!(0, vendure_licence_sdk_1.isLicensed)(plugin_1.VisitorAnalyticsPlugin.getLicenceStatus())) {
439
+ return res.status(402).json((0, vendure_licence_sdk_1.premiumFeatureError)('vendure-plugin-visitor-analytics'));
440
+ }
400
441
  res.setHeader('Content-Type', 'text/event-stream');
401
442
  res.setHeader('Cache-Control', 'no-cache, no-transform');
402
443
  res.setHeader('Connection', 'keep-alive');
@@ -656,6 +697,9 @@ let VisitorTrackingController = class VisitorTrackingController {
656
697
  async createGoal(ctx, body, res) {
657
698
  if (!requireAdmin(ctx, res))
658
699
  return;
700
+ if (!(0, vendure_licence_sdk_1.isLicensed)(plugin_1.VisitorAnalyticsPlugin.getLicenceStatus())) {
701
+ return res.status(402).json((0, vendure_licence_sdk_1.premiumFeatureError)('vendure-plugin-visitor-analytics'));
702
+ }
659
703
  const repo = this.connection.rawConnection.getRepository(conversion_goal_entity_1.ConversionGoal);
660
704
  const row = repo.create({
661
705
  channelId: Number(body === null || body === void 0 ? void 0 : body.channelId) || 1,
@@ -727,6 +771,9 @@ let VisitorTrackingController = class VisitorTrackingController {
727
771
  async exportCsv(ctx, req, res) {
728
772
  if (!requireAdmin(ctx, res))
729
773
  return;
774
+ if (!(0, vendure_licence_sdk_1.isLicensed)(plugin_1.VisitorAnalyticsPlugin.getLicenceStatus())) {
775
+ return res.status(402).json((0, vendure_licence_sdk_1.premiumFeatureError)('vendure-plugin-visitor-analytics'));
776
+ }
730
777
  const days = Math.min(Math.max(parseInt(String(req.query.days || '7'), 10) || 7, 1), 90);
731
778
  const rows = await this.connection.rawConnection.query(`SELECT createdAt, visitorId, sessionId, customerId, channelId,
732
779
  type, url, title, referrerDomain,