@adobe/spacecat-shared-athena-client 1.4.1 → 1.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.
- package/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/index.d.ts +47 -0
- package/src/index.js +7 -1
- package/src/pta2/queries.js +150 -0
- package/src/traffic-analysis/traffic-data-base-response.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-athena-client-v1.6.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-athena-client-v1.5.0...@adobe/spacecat-shared-athena-client-v1.6.0) (2025-11-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* added device to PTR Results structure ([#1116](https://github.com/adobe/spacecat-shared/issues/1116)) ([f80fc3f](https://github.com/adobe/spacecat-shared/commit/f80fc3ff63d5b979927116cfd3fb759160bbd09f))
|
|
7
|
+
|
|
8
|
+
# [@adobe/spacecat-shared-athena-client-v1.5.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-athena-client-v1.4.1...@adobe/spacecat-shared-athena-client-v1.5.0) (2025-11-10)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* added trend info to PTAv2 query ([#1109](https://github.com/adobe/spacecat-shared/issues/1109)) ([051a12a](https://github.com/adobe/spacecat-shared/commit/051a12a20fd10641b1e80dd31a3102a72c931bf9))
|
|
14
|
+
|
|
1
15
|
# [@adobe/spacecat-shared-athena-client-v1.4.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-athena-client-v1.4.0...@adobe/spacecat-shared-athena-client-v1.4.1) (2025-11-08)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -82,3 +82,50 @@ export declare class AWSAthenaClient {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
export type Context = Parameters<typeof AWSAthenaClient.fromContext>[0];
|
|
85
|
+
|
|
86
|
+
// PTA2 Query Types
|
|
87
|
+
export interface PTAQueryParams {
|
|
88
|
+
siteId: string;
|
|
89
|
+
tableName: string;
|
|
90
|
+
week?: number;
|
|
91
|
+
month?: number;
|
|
92
|
+
year: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface PTASummaryData {
|
|
96
|
+
pageviews: number;
|
|
97
|
+
click_rate: number;
|
|
98
|
+
engagement_rate: number;
|
|
99
|
+
bounce_rate: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface PTATrendData {
|
|
103
|
+
pageviews: number;
|
|
104
|
+
click_rate: number;
|
|
105
|
+
engagement_rate: number;
|
|
106
|
+
bounce_rate: number;
|
|
107
|
+
trends: {
|
|
108
|
+
pageviews: number | null;
|
|
109
|
+
click_rate: number | null;
|
|
110
|
+
engagement_rate: number | null;
|
|
111
|
+
bounce_rate: number | null;
|
|
112
|
+
} | null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export declare function getPreviousPeriod(params: {
|
|
116
|
+
week?: number;
|
|
117
|
+
month?: number;
|
|
118
|
+
year: number;
|
|
119
|
+
}): { week?: number; month?: number; year: number };
|
|
120
|
+
|
|
121
|
+
export declare function getPTASummaryQuery(params: PTAQueryParams): string;
|
|
122
|
+
|
|
123
|
+
export declare function getPTASummaryWithTrendQuery(params: PTAQueryParams): string;
|
|
124
|
+
|
|
125
|
+
export declare const PTASummaryResponseDto: {
|
|
126
|
+
toJSON: (data: Record<string, unknown>) => PTASummaryData;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export declare const PTASummaryWithTrendResponseDto: {
|
|
130
|
+
toJSON: (data: Array<Record<string, unknown>>) => PTATrendData;
|
|
131
|
+
};
|
package/src/index.js
CHANGED
|
@@ -265,4 +265,10 @@ export {
|
|
|
265
265
|
export { TrafficDataResponseDto } from './traffic-analysis/traffic-data-base-response.js';
|
|
266
266
|
export { TrafficDataWithCWVDto } from './traffic-analysis/traffic-data-with-cwv.js';
|
|
267
267
|
|
|
268
|
-
export {
|
|
268
|
+
export {
|
|
269
|
+
getPreviousPeriod,
|
|
270
|
+
getPTASummaryQuery,
|
|
271
|
+
getPTASummaryWithTrendQuery,
|
|
272
|
+
PTASummaryResponseDto,
|
|
273
|
+
PTASummaryWithTrendResponseDto,
|
|
274
|
+
} from './pta2/queries.js';
|
package/src/pta2/queries.js
CHANGED
|
@@ -12,6 +12,40 @@
|
|
|
12
12
|
|
|
13
13
|
import { getTemporalCondition } from '@adobe/spacecat-shared-utils';
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Calculates the previous period (week or month) for trend comparison.
|
|
17
|
+
* @param {Object} params - Period parameters
|
|
18
|
+
* @param {number} params.week - Week number (optional)
|
|
19
|
+
* @param {number} params.month - Month number (optional)
|
|
20
|
+
* @param {number} params.year - Year number
|
|
21
|
+
* @returns {Object} Previous period with week/month and year
|
|
22
|
+
*/
|
|
23
|
+
export function getPreviousPeriod({ week, month, year }) {
|
|
24
|
+
if (week !== undefined) {
|
|
25
|
+
// Calculate previous week
|
|
26
|
+
const prevWeek = week - 1;
|
|
27
|
+
if (prevWeek < 1) {
|
|
28
|
+
// Move to previous year's last week
|
|
29
|
+
const prevYear = year - 1;
|
|
30
|
+
// Approximate last week (52 or 53)
|
|
31
|
+
return { week: 52, year: prevYear };
|
|
32
|
+
}
|
|
33
|
+
return { week: prevWeek, year };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (month !== undefined) {
|
|
37
|
+
// Calculate previous month
|
|
38
|
+
const prevMonth = month - 1;
|
|
39
|
+
if (prevMonth < 1) {
|
|
40
|
+
// Move to previous year's December
|
|
41
|
+
return { month: 12, year: year - 1 };
|
|
42
|
+
}
|
|
43
|
+
return { month: prevMonth, year };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
throw new Error('Either week or month must be provided');
|
|
47
|
+
}
|
|
48
|
+
|
|
15
49
|
/**
|
|
16
50
|
* Generates the PTA summary query template using template literals.
|
|
17
51
|
* @param {Object} params - Template parameters
|
|
@@ -56,6 +90,61 @@ export function getPTASummaryQuery({
|
|
|
56
90
|
`;
|
|
57
91
|
}
|
|
58
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Generates a PTA summary query that includes both current and previous period data
|
|
95
|
+
* for trend analysis. More efficient than making two separate queries.
|
|
96
|
+
* @param {Object} params - Template parameters
|
|
97
|
+
* @param {string} params.siteId - Site ID
|
|
98
|
+
* @param {string} params.tableName - Table name
|
|
99
|
+
* @param {number} params.week - Week number (either week or month must be provided)
|
|
100
|
+
* @param {number} params.month - Month number (either week or month must be provided)
|
|
101
|
+
* @param {number} params.year - Year number
|
|
102
|
+
* @returns {string} The SQL query string with both current and previous period data
|
|
103
|
+
*/
|
|
104
|
+
export function getPTASummaryWithTrendQuery({
|
|
105
|
+
siteId,
|
|
106
|
+
tableName,
|
|
107
|
+
week,
|
|
108
|
+
month,
|
|
109
|
+
year,
|
|
110
|
+
}) {
|
|
111
|
+
if (!siteId || !tableName) {
|
|
112
|
+
throw new Error('Missing required parameters: siteId, or tableName');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if ((!week && !month) || !year) {
|
|
116
|
+
throw new Error('Missing required parameters: week, month or year');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const currentTemporalCondition = getTemporalCondition({ week, month, year });
|
|
120
|
+
const previousPeriod = getPreviousPeriod({ week, month, year });
|
|
121
|
+
const previousTemporalCondition = getTemporalCondition(previousPeriod);
|
|
122
|
+
|
|
123
|
+
return `
|
|
124
|
+
SELECT
|
|
125
|
+
period,
|
|
126
|
+
CAST(SUM(pageviews) AS BIGINT) AS total_pageviews,
|
|
127
|
+
CAST(SUM(clicked) AS BIGINT) AS total_clicks,
|
|
128
|
+
CAST(SUM(engaged) AS BIGINT) AS total_engaged,
|
|
129
|
+
COUNT(*) AS total_rows,
|
|
130
|
+
CAST(SUM(clicked) AS DOUBLE) / NULLIF(COUNT(*), 0) AS click_rate,
|
|
131
|
+
CAST(SUM(engaged) AS DOUBLE) / NULLIF(COUNT(*), 0) AS engagement_rate,
|
|
132
|
+
1 - CAST(SUM(engaged) AS DOUBLE) / NULLIF(COUNT(*), 0) AS bounce_rate
|
|
133
|
+
FROM (
|
|
134
|
+
SELECT *, 'current' as period FROM ${tableName}
|
|
135
|
+
WHERE siteid = '${siteId}'
|
|
136
|
+
AND (${currentTemporalCondition})
|
|
137
|
+
AND trf_type = 'paid'
|
|
138
|
+
UNION ALL
|
|
139
|
+
SELECT *, 'previous' as period FROM ${tableName}
|
|
140
|
+
WHERE siteid = '${siteId}'
|
|
141
|
+
AND (${previousTemporalCondition})
|
|
142
|
+
AND trf_type = 'paid'
|
|
143
|
+
)
|
|
144
|
+
GROUP BY period
|
|
145
|
+
`;
|
|
146
|
+
}
|
|
147
|
+
|
|
59
148
|
export const PTASummaryResponseDto = {
|
|
60
149
|
/**
|
|
61
150
|
* Converts a traffic data object into a JSON object.
|
|
@@ -74,3 +163,64 @@ export const PTASummaryResponseDto = {
|
|
|
74
163
|
bounce_rate: data.bounce_rate,
|
|
75
164
|
}),
|
|
76
165
|
};
|
|
166
|
+
|
|
167
|
+
export const PTASummaryWithTrendResponseDto = {
|
|
168
|
+
/**
|
|
169
|
+
* Converts trend data (array with current and previous periods)
|
|
170
|
+
* into a JSON object with current metrics and trends.
|
|
171
|
+
* @param {Array<object>} data - Array of traffic data objects with 'period' field.
|
|
172
|
+
* @returns {{
|
|
173
|
+
* pageviews: number,
|
|
174
|
+
* click_rate: number,
|
|
175
|
+
* engagement_rate: number,
|
|
176
|
+
* bounce_rate: number,
|
|
177
|
+
* trends: {
|
|
178
|
+
* pageviews: number,
|
|
179
|
+
* click_rate: number,
|
|
180
|
+
* engagement_rate: number,
|
|
181
|
+
* bounce_rate: number
|
|
182
|
+
* }
|
|
183
|
+
* }} JSON object with current metrics and trend percentages.
|
|
184
|
+
*/
|
|
185
|
+
toJSON: (data) => {
|
|
186
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
187
|
+
throw new Error('Expected an array with at least one period');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const currentData = data.find((row) => row.period === 'current');
|
|
191
|
+
const previousData = data.find((row) => row.period === 'previous');
|
|
192
|
+
|
|
193
|
+
if (!currentData) {
|
|
194
|
+
throw new Error('Current period data not found');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const current = {
|
|
198
|
+
pageviews: currentData.total_pageviews,
|
|
199
|
+
click_rate: currentData.click_rate,
|
|
200
|
+
engagement_rate: currentData.engagement_rate,
|
|
201
|
+
bounce_rate: currentData.bounce_rate,
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// Calculate trend percentages (null if no previous data)
|
|
205
|
+
const trends = previousData ? {
|
|
206
|
+
pageviews: previousData.total_pageviews > 0
|
|
207
|
+
? ((current.pageviews - previousData.total_pageviews) / previousData.total_pageviews) * 100
|
|
208
|
+
: null,
|
|
209
|
+
click_rate: previousData.click_rate > 0
|
|
210
|
+
? ((current.click_rate - previousData.click_rate) / previousData.click_rate) * 100
|
|
211
|
+
: null,
|
|
212
|
+
engagement_rate: previousData.engagement_rate > 0
|
|
213
|
+
? ((current.engagement_rate - previousData.engagement_rate)
|
|
214
|
+
/ previousData.engagement_rate) * 100
|
|
215
|
+
: null,
|
|
216
|
+
bounce_rate: previousData.bounce_rate > 0
|
|
217
|
+
? ((current.bounce_rate - previousData.bounce_rate) / previousData.bounce_rate) * 100
|
|
218
|
+
: null,
|
|
219
|
+
} : null;
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
...current,
|
|
223
|
+
trends,
|
|
224
|
+
};
|
|
225
|
+
},
|
|
226
|
+
};
|