@socialgouv/matomo-postgres 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.js ADDED
@@ -0,0 +1,79 @@
1
+ const pAll = require("p-all");
2
+ const debug = require("debug")("index");
3
+ const eachDayOfInterval = require("date-fns/eachDayOfInterval");
4
+ const PiwikClient = require("piwik-client");
5
+ const { Client } = require("pg");
6
+
7
+ const { MATOMO_KEY, MATOMO_URL, MATOMO_SITE, PGDATABASE, DESTINATION_TABLE, OFFSET } = require("./config");
8
+
9
+ const { createTable } = require("./createTable");
10
+ const { importDate } = require("./importDate");
11
+
12
+ // run a sync with a 3-days range
13
+ /**
14
+ *
15
+ * @param {string} [date]
16
+ * @returns
17
+ */
18
+ async function run(date) {
19
+ debug("run, date=" + date);
20
+ const client = new Client({ connectionString: PGDATABASE });
21
+ await client.connect();
22
+
23
+ const piwik = new PiwikClient(MATOMO_URL, MATOMO_KEY);
24
+
25
+ await createTable(client);
26
+
27
+ // priority:
28
+ // - optional parameter date
29
+ // - last event in the table
30
+ // - optional env.STARTDATE
31
+ // - today
32
+
33
+ let referenceDate;
34
+ if (!referenceDate && date) referenceDate = new Date(date);
35
+ if (!referenceDate) referenceDate = await findLastEventInMatomo(client);
36
+ if (!referenceDate && process.env.STARTDATE) referenceDate = new Date(process.env.STARTDATE);
37
+ if (!referenceDate) referenceDate = new Date();
38
+
39
+ // @ts-ignore
40
+ const dates = eachDayOfInterval({
41
+ start: referenceDate,
42
+ end: new Date(),
43
+ });
44
+
45
+ debug(`import : ${dates.join(", ")}`);
46
+
47
+ // for each date, serial-import data
48
+ const res = await pAll(
49
+ dates.map((date) => () => importDate(client, piwik.api.bind(piwik), date)),
50
+ { concurrency: 1, stopOnError: true }
51
+ );
52
+
53
+ await client.end();
54
+ debug("close");
55
+
56
+ return res;
57
+ }
58
+
59
+ module.exports = run;
60
+
61
+ if (require.main === module) {
62
+ (async () => {
63
+ if (!MATOMO_SITE) return console.error("Missing env MATOMO_SITE");
64
+ if (!MATOMO_KEY) return console.error("Missing env MATOMO_KEY");
65
+ if (!PGDATABASE) return console.error("Missing env PGDATABASE");
66
+ await run();
67
+ debug("run finished");
68
+ })();
69
+ }
70
+
71
+ async function findLastEventInMatomo(client) {
72
+ const a = await client.query(
73
+ `select action_timestamp from ${client.escapeIdentifier(DESTINATION_TABLE)} order by action_timestamp desc limit 1`
74
+ );
75
+ if (!a.rows.length || !a.rows[0].action_timestamp) return null;
76
+ const d = new Date(a.rows[0].action_timestamp);
77
+ d.setDate(d.getDate() - +OFFSET);
78
+ return d;
79
+ }
@@ -0,0 +1,30 @@
1
+ export * from "./matomo";
2
+
3
+ export type Event = {
4
+ idsite: string;
5
+ idvisit: string;
6
+ actions: string;
7
+ country: string;
8
+ region: string;
9
+ city: string;
10
+ operatingsystemname: string;
11
+ devicemodel: string;
12
+ devicebrand: string;
13
+ visitduration: string;
14
+ dayssincefirstvisit: string;
15
+ visitortype: string;
16
+ sitename: string;
17
+ userid: string;
18
+ serverdateprettyfirstaction: string;
19
+ action_id: string;
20
+ action_type: string;
21
+ action_eventcategory: string;
22
+ action_eventaction: string;
23
+ action_eventname: string;
24
+ action_eventvalue: string;
25
+ action_timespent: string;
26
+ action_timestamp: string;
27
+ action_url: string;
28
+ usercustomproperties: Record<string, string>;
29
+ usercustomdimensions: Record<string, string>;
30
+ };
@@ -0,0 +1,208 @@
1
+ export type Visits = Visit[];
2
+
3
+ export type Visit = {
4
+ idSite: string;
5
+ idVisit: string;
6
+ visitIp: any;
7
+ visitorId: boolean;
8
+ fingerprint: boolean;
9
+ actionDetails: ActionDetail[];
10
+ goalConversions: number;
11
+ siteCurrency: string;
12
+ siteCurrencySymbol: string;
13
+ serverDate: string;
14
+ visitServerHour: string;
15
+ lastActionTimestamp: number;
16
+ lastActionDateTime: string;
17
+ siteName: string;
18
+ serverTimestamp: number;
19
+ firstActionTimestamp: number;
20
+ serverTimePretty: string;
21
+ serverDatePretty: string;
22
+ serverDatePrettyFirstAction: string;
23
+ serverTimePrettyFirstAction: string;
24
+ userId: any;
25
+ visitorType: string;
26
+ visitorTypeIcon: string;
27
+ visitConverted: string;
28
+ visitConvertedIcon?: string;
29
+ visitCount: string;
30
+ visitEcommerceStatus: string;
31
+ visitEcommerceStatusIcon?: string;
32
+ daysSinceFirstVisit: number;
33
+ secondsSinceFirstVisit: string;
34
+ daysSinceLastEcommerceOrder: number;
35
+ secondsSinceLastEcommerceOrder: string;
36
+ visitDuration: string;
37
+ visitDurationPretty: string;
38
+ searches: string;
39
+ actions: string;
40
+ interactions: string;
41
+ referrerType: string;
42
+ referrerTypeName: string;
43
+ referrerName: string;
44
+ referrerKeyword: string;
45
+ referrerKeywordPosition: any;
46
+ referrerUrl?: string;
47
+ referrerSearchEngineUrl?: string;
48
+ referrerSearchEngineIcon?: string;
49
+ referrerSocialNetworkUrl?: string;
50
+ referrerSocialNetworkIcon?: string;
51
+ languageCode: string;
52
+ language: string;
53
+ deviceType: string;
54
+ deviceTypeIcon: string;
55
+ deviceBrand: string;
56
+ deviceModel: string;
57
+ operatingSystem: string;
58
+ operatingSystemName: string;
59
+ operatingSystemIcon: string;
60
+ operatingSystemCode: string;
61
+ operatingSystemVersion: string;
62
+ browserFamily: string;
63
+ browserFamilyDescription: string;
64
+ browser: string;
65
+ browserName: string;
66
+ browserIcon: string;
67
+ browserCode: string;
68
+ browserVersion: string;
69
+ totalEcommerceRevenue: string;
70
+ totalEcommerceConversions: string;
71
+ totalEcommerceItems: string;
72
+ totalAbandonedCartsRevenue: string;
73
+ totalAbandonedCarts: string;
74
+ totalAbandonedCartsItems: string;
75
+ events: string;
76
+ continent: string;
77
+ continentCode: string;
78
+ country: string;
79
+ countryCode: string;
80
+ countryFlag: string;
81
+ region?: string;
82
+ regionCode?: string;
83
+ city?: string;
84
+ location: string;
85
+ latitude: string;
86
+ longitude: string;
87
+ visitLocalTime: string;
88
+ visitLocalHour: string;
89
+ daysSinceLastVisit: number;
90
+ secondsSinceLastVisit: string;
91
+ resolution: string;
92
+ plugins: string;
93
+ pluginsIcons?: PluginsIcon[];
94
+ dimension1?: string;
95
+ dimension2: string;
96
+ dimension3?: string;
97
+ dimension4?: string;
98
+ dimension5?: string;
99
+ experiments: Experiment[];
100
+ customVariables: any;
101
+ formConversions: number;
102
+ sessionReplayUrl: any;
103
+ campaignId: string;
104
+ campaignContent: string;
105
+ campaignKeyword: string;
106
+ campaignMedium: string;
107
+ campaignName: string;
108
+ campaignSource: string;
109
+ campaignGroup: string;
110
+ campaignPlacement: string;
111
+ };
112
+
113
+ export interface ActionDetail {
114
+ type: string;
115
+ url?: string;
116
+ pageTitle?: string;
117
+ pageIdAction?: string;
118
+ idpageview?: string;
119
+ serverTimePretty: string;
120
+ pageId?: string;
121
+ pageviewPosition?: string;
122
+ title: string;
123
+ subtitle?: string;
124
+ icon: string;
125
+ iconSVG?: string;
126
+ timestamp: number;
127
+ dimension1?: string;
128
+ dimension2?: string;
129
+ dimension3?: string;
130
+ dimension4?: string;
131
+ dimension5?: string;
132
+ formName?: string;
133
+ formId?: string;
134
+ formStatus?: string;
135
+ converted?: string;
136
+ submitted?: number;
137
+ timeToFirstSubmission?: string;
138
+ timeSpent: any;
139
+ timeHesitation?: string;
140
+ leftBlank?: number;
141
+ fields?: Field[];
142
+ eventCategory?: string;
143
+ eventAction?: string;
144
+ timeSpentPretty?: string;
145
+ eventName?: string;
146
+ eventValue?: number;
147
+ revenue: any;
148
+ items?: string;
149
+ itemDetails?: ItemDetail[];
150
+ customVariables?: CustomVariables;
151
+ server_time?: string;
152
+ goalName?: string;
153
+ goalId?: string;
154
+ goalPageId?: string;
155
+ orderId?: string;
156
+ revenueSubTotal?: number;
157
+ revenueTax?: number;
158
+ revenueShipping?: number;
159
+ revenueDiscount?: number;
160
+ }
161
+
162
+ export interface Field {
163
+ fieldName: string;
164
+ timeSpent: string;
165
+ timeHesitation: string;
166
+ leftBlank: string;
167
+ submitted: string;
168
+ }
169
+
170
+ export interface ItemDetail {
171
+ itemSKU: string;
172
+ itemName: string;
173
+ itemCategory: string;
174
+ price: any;
175
+ quantity: string;
176
+ categories: string[];
177
+ }
178
+
179
+ export interface CustomVariables {
180
+ "1": N1;
181
+ "2": N2;
182
+ }
183
+
184
+ export interface N1 {
185
+ customVariablePageName1: string;
186
+ customVariablePageValue1: string;
187
+ }
188
+
189
+ export interface N2 {
190
+ customVariablePageName2: string;
191
+ customVariablePageValue2: string;
192
+ }
193
+
194
+ export interface PluginsIcon {
195
+ pluginIcon: string;
196
+ pluginName: string;
197
+ }
198
+
199
+ export interface Experiment {
200
+ idexperiment: string;
201
+ name: string;
202
+ variation: Variation;
203
+ }
204
+
205
+ export interface Variation {
206
+ idvariation: any;
207
+ name: string;
208
+ }