@houtini/better-search-console 1.0.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/LICENSE +189 -0
- package/README.md +334 -0
- package/better-search-console.jpg +0 -0
- package/dist/core/DataRetention.d.ts +49 -0
- package/dist/core/DataRetention.d.ts.map +1 -0
- package/dist/core/DataRetention.js +165 -0
- package/dist/core/DataRetention.js.map +1 -0
- package/dist/core/DataSync.d.ts +24 -0
- package/dist/core/DataSync.d.ts.map +1 -0
- package/dist/core/DataSync.js +247 -0
- package/dist/core/DataSync.js.map +1 -0
- package/dist/core/Database.d.ts +29 -0
- package/dist/core/Database.d.ts.map +1 -0
- package/dist/core/Database.js +205 -0
- package/dist/core/Database.js.map +1 -0
- package/dist/core/GscClient.d.ts +23 -0
- package/dist/core/GscClient.d.ts.map +1 -0
- package/dist/core/GscClient.js +92 -0
- package/dist/core/GscClient.js.map +1 -0
- package/dist/core/SyncManager.d.ts +66 -0
- package/dist/core/SyncManager.d.ts.map +1 -0
- package/dist/core/SyncManager.js +368 -0
- package/dist/core/SyncManager.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/overview/src/ui/overview.html +185 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +441 -0
- package/dist/server.js.map +1 -0
- package/dist/src/ui/dashboard.html +437 -0
- package/dist/sync-progress/src/ui/sync-progress.html +147 -0
- package/dist/tools/compare-periods.d.ts +3 -0
- package/dist/tools/compare-periods.d.ts.map +1 -0
- package/dist/tools/compare-periods.js +127 -0
- package/dist/tools/compare-periods.js.map +1 -0
- package/dist/tools/get-dashboard.d.ts +10 -0
- package/dist/tools/get-dashboard.d.ts.map +1 -0
- package/dist/tools/get-dashboard.js +310 -0
- package/dist/tools/get-dashboard.js.map +1 -0
- package/dist/tools/get-insights.d.ts +3 -0
- package/dist/tools/get-insights.d.ts.map +1 -0
- package/dist/tools/get-insights.js +509 -0
- package/dist/tools/get-insights.js.map +1 -0
- package/dist/tools/get-overview.d.ts +36 -0
- package/dist/tools/get-overview.d.ts.map +1 -0
- package/dist/tools/get-overview.js +111 -0
- package/dist/tools/get-overview.js.map +1 -0
- package/dist/tools/helpers.d.ts +67 -0
- package/dist/tools/helpers.d.ts.map +1 -0
- package/dist/tools/helpers.js +239 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/list-properties.d.ts +4 -0
- package/dist/tools/list-properties.d.ts.map +1 -0
- package/dist/tools/list-properties.js +35 -0
- package/dist/tools/list-properties.js.map +1 -0
- package/dist/tools/query-data.d.ts +12 -0
- package/dist/tools/query-data.d.ts.map +1 -0
- package/dist/tools/query-data.js +20 -0
- package/dist/tools/query-data.js.map +1 -0
- package/dist/tools/sync-data.d.ts +11 -0
- package/dist/tools/sync-data.d.ts.map +1 -0
- package/dist/tools/sync-data.js +62 -0
- package/dist/tools/sync-data.js.map +1 -0
- package/dist/types/index.d.ts +101 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { Database } from '../core/Database.js';
|
|
3
|
+
import { getDbPath, getPeriodDates } from './helpers.js';
|
|
4
|
+
export function getInsights(params) {
|
|
5
|
+
const { siteUrl, insight, dateRange = '28d' } = params;
|
|
6
|
+
const dbPath = getDbPath(siteUrl);
|
|
7
|
+
if (!existsSync(dbPath)) {
|
|
8
|
+
throw new Error(`No database found for "${siteUrl}". Run sync_gsc_data first.`);
|
|
9
|
+
}
|
|
10
|
+
const handler = insightHandlers[insight];
|
|
11
|
+
if (!handler) {
|
|
12
|
+
throw new Error(`Unknown insight type: "${insight}". Valid types: ${Object.keys(insightHandlers).join(', ')}`);
|
|
13
|
+
}
|
|
14
|
+
const { current, prior } = getPeriodDates(dateRange);
|
|
15
|
+
const db = new Database(dbPath);
|
|
16
|
+
try {
|
|
17
|
+
return handler(db, params, current, prior);
|
|
18
|
+
}
|
|
19
|
+
finally {
|
|
20
|
+
db.close();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Build WHERE clause fragments from common filter params */
|
|
24
|
+
function buildFilters(params) {
|
|
25
|
+
const clauses = [];
|
|
26
|
+
const values = [];
|
|
27
|
+
if (params.pageFilter) {
|
|
28
|
+
clauses.push('page LIKE ?');
|
|
29
|
+
values.push(`%${params.pageFilter}%`);
|
|
30
|
+
}
|
|
31
|
+
if (params.queryFilter) {
|
|
32
|
+
clauses.push('query LIKE ?');
|
|
33
|
+
values.push(`%${params.queryFilter}%`);
|
|
34
|
+
}
|
|
35
|
+
if (params.device) {
|
|
36
|
+
clauses.push('device = ?');
|
|
37
|
+
values.push(params.device);
|
|
38
|
+
}
|
|
39
|
+
if (params.country) {
|
|
40
|
+
clauses.push('country = ?');
|
|
41
|
+
values.push(params.country);
|
|
42
|
+
}
|
|
43
|
+
return { clauses, values };
|
|
44
|
+
}
|
|
45
|
+
function filterSQL(params) {
|
|
46
|
+
const { clauses } = buildFilters(params);
|
|
47
|
+
return clauses.length > 0 ? ' AND ' + clauses.join(' AND ') : '';
|
|
48
|
+
}
|
|
49
|
+
function filterValues(params) {
|
|
50
|
+
return buildFilters(params).values;
|
|
51
|
+
}
|
|
52
|
+
// --- Insight Handlers ---
|
|
53
|
+
const insightHandlers = {
|
|
54
|
+
summary: (db, params, current, prior) => {
|
|
55
|
+
const f = filterSQL(params);
|
|
56
|
+
const fv = filterValues(params);
|
|
57
|
+
const currentRow = db.queryOne(`
|
|
58
|
+
SELECT
|
|
59
|
+
COALESCE(SUM(clicks), 0) as clicks,
|
|
60
|
+
COALESCE(SUM(impressions), 0) as impressions,
|
|
61
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
62
|
+
ROUND(AVG(position), 1) as avg_position
|
|
63
|
+
FROM search_analytics
|
|
64
|
+
WHERE date BETWEEN ? AND ?${f}
|
|
65
|
+
`, [current.startDate, current.endDate, ...fv]);
|
|
66
|
+
const priorRow = db.queryOne(`
|
|
67
|
+
SELECT
|
|
68
|
+
COALESCE(SUM(clicks), 0) as clicks,
|
|
69
|
+
COALESCE(SUM(impressions), 0) as impressions,
|
|
70
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
71
|
+
ROUND(AVG(position), 1) as avg_position
|
|
72
|
+
FROM search_analytics
|
|
73
|
+
WHERE date BETWEEN ? AND ?${f}
|
|
74
|
+
`, [prior.startDate, prior.endDate, ...fv]);
|
|
75
|
+
const pctChange = (curr, prev) => prev === 0 ? null : Math.round(((curr - prev) / prev) * 1000) / 10;
|
|
76
|
+
return {
|
|
77
|
+
insight: 'summary',
|
|
78
|
+
dateRange: { current, prior },
|
|
79
|
+
current: {
|
|
80
|
+
clicks: currentRow.clicks,
|
|
81
|
+
impressions: currentRow.impressions,
|
|
82
|
+
ctr: currentRow.ctr,
|
|
83
|
+
avgPosition: currentRow.avg_position,
|
|
84
|
+
},
|
|
85
|
+
prior: {
|
|
86
|
+
clicks: priorRow.clicks,
|
|
87
|
+
impressions: priorRow.impressions,
|
|
88
|
+
ctr: priorRow.ctr,
|
|
89
|
+
avgPosition: priorRow.avg_position,
|
|
90
|
+
},
|
|
91
|
+
changes: {
|
|
92
|
+
clicks: currentRow.clicks - priorRow.clicks,
|
|
93
|
+
clicksPct: pctChange(currentRow.clicks, priorRow.clicks),
|
|
94
|
+
impressions: currentRow.impressions - priorRow.impressions,
|
|
95
|
+
impressionsPct: pctChange(currentRow.impressions, priorRow.impressions),
|
|
96
|
+
ctr: currentRow.ctr !== null && priorRow.ctr !== null
|
|
97
|
+
? Math.round((currentRow.ctr - priorRow.ctr) * 10000) / 10000
|
|
98
|
+
: null,
|
|
99
|
+
ctrPct: currentRow.ctr !== null && priorRow.ctr !== null
|
|
100
|
+
? pctChange(currentRow.ctr, priorRow.ctr)
|
|
101
|
+
: null,
|
|
102
|
+
avgPosition: currentRow.avg_position !== null && priorRow.avg_position !== null
|
|
103
|
+
? Math.round((currentRow.avg_position - priorRow.avg_position) * 10) / 10
|
|
104
|
+
: null,
|
|
105
|
+
avgPositionPct: currentRow.avg_position !== null && priorRow.avg_position !== null
|
|
106
|
+
? pctChange(currentRow.avg_position, priorRow.avg_position)
|
|
107
|
+
: null,
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
top_queries: (db, params, current, _prior) => {
|
|
112
|
+
const limit = params.limit || 50;
|
|
113
|
+
const f = filterSQL(params);
|
|
114
|
+
const fv = filterValues(params);
|
|
115
|
+
const rows = db.query(`
|
|
116
|
+
SELECT query,
|
|
117
|
+
SUM(clicks) as clicks,
|
|
118
|
+
SUM(impressions) as impressions,
|
|
119
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
120
|
+
ROUND(AVG(position), 1) as avg_position
|
|
121
|
+
FROM search_analytics
|
|
122
|
+
WHERE date BETWEEN ? AND ? AND query IS NOT NULL${f}
|
|
123
|
+
GROUP BY query
|
|
124
|
+
ORDER BY clicks DESC
|
|
125
|
+
LIMIT ?
|
|
126
|
+
`, [current.startDate, current.endDate, ...fv, limit]);
|
|
127
|
+
return { insight: 'top_queries', dateRange: current, rows };
|
|
128
|
+
},
|
|
129
|
+
top_pages: (db, params, current, _prior) => {
|
|
130
|
+
const limit = params.limit || 50;
|
|
131
|
+
const f = filterSQL(params);
|
|
132
|
+
const fv = filterValues(params);
|
|
133
|
+
const rows = db.query(`
|
|
134
|
+
SELECT page,
|
|
135
|
+
SUM(clicks) as clicks,
|
|
136
|
+
SUM(impressions) as impressions,
|
|
137
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
138
|
+
ROUND(AVG(position), 1) as avg_position
|
|
139
|
+
FROM search_analytics
|
|
140
|
+
WHERE date BETWEEN ? AND ? AND page IS NOT NULL${f}
|
|
141
|
+
GROUP BY page
|
|
142
|
+
ORDER BY clicks DESC
|
|
143
|
+
LIMIT ?
|
|
144
|
+
`, [current.startDate, current.endDate, ...fv, limit]);
|
|
145
|
+
return { insight: 'top_pages', dateRange: current, rows };
|
|
146
|
+
},
|
|
147
|
+
growing_queries: (db, params, current, prior) => {
|
|
148
|
+
const limit = params.limit || 50;
|
|
149
|
+
const f = filterSQL(params);
|
|
150
|
+
const fv = filterValues(params);
|
|
151
|
+
const rows = db.query(`
|
|
152
|
+
SELECT query,
|
|
153
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as current_clicks,
|
|
154
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as prior_clicks,
|
|
155
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END)
|
|
156
|
+
- SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as click_change,
|
|
157
|
+
ROUND(
|
|
158
|
+
(SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END)
|
|
159
|
+
- SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END))
|
|
160
|
+
* 100.0
|
|
161
|
+
/ NULLIF(SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END), 0),
|
|
162
|
+
1
|
|
163
|
+
) as pct_change,
|
|
164
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN impressions ELSE 0 END) as current_impressions,
|
|
165
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN impressions ELSE 0 END) as prior_impressions
|
|
166
|
+
FROM search_analytics
|
|
167
|
+
WHERE query IS NOT NULL
|
|
168
|
+
AND (date BETWEEN ? AND ? OR date BETWEEN ? AND ?)${f}
|
|
169
|
+
GROUP BY query
|
|
170
|
+
HAVING current_clicks > 0
|
|
171
|
+
ORDER BY click_change DESC
|
|
172
|
+
LIMIT ?
|
|
173
|
+
`, [
|
|
174
|
+
current.startDate, current.endDate,
|
|
175
|
+
prior.startDate, prior.endDate,
|
|
176
|
+
current.startDate, current.endDate,
|
|
177
|
+
prior.startDate, prior.endDate,
|
|
178
|
+
current.startDate, current.endDate,
|
|
179
|
+
prior.startDate, prior.endDate,
|
|
180
|
+
prior.startDate, prior.endDate,
|
|
181
|
+
current.startDate, current.endDate,
|
|
182
|
+
prior.startDate, prior.endDate,
|
|
183
|
+
current.startDate, current.endDate,
|
|
184
|
+
prior.startDate, prior.endDate,
|
|
185
|
+
...fv,
|
|
186
|
+
limit,
|
|
187
|
+
]);
|
|
188
|
+
return { insight: 'growing_queries', dateRange: { current, prior }, rows };
|
|
189
|
+
},
|
|
190
|
+
declining_queries: (db, params, current, prior) => {
|
|
191
|
+
const limit = params.limit || 50;
|
|
192
|
+
const f = filterSQL(params);
|
|
193
|
+
const fv = filterValues(params);
|
|
194
|
+
const rows = db.query(`
|
|
195
|
+
SELECT query,
|
|
196
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as current_clicks,
|
|
197
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as prior_clicks,
|
|
198
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END)
|
|
199
|
+
- SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as click_change,
|
|
200
|
+
ROUND(
|
|
201
|
+
(SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END)
|
|
202
|
+
- SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END))
|
|
203
|
+
* 100.0
|
|
204
|
+
/ NULLIF(SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END), 0),
|
|
205
|
+
1
|
|
206
|
+
) as pct_change,
|
|
207
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN impressions ELSE 0 END) as current_impressions,
|
|
208
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN impressions ELSE 0 END) as prior_impressions
|
|
209
|
+
FROM search_analytics
|
|
210
|
+
WHERE query IS NOT NULL
|
|
211
|
+
AND (date BETWEEN ? AND ? OR date BETWEEN ? AND ?)${f}
|
|
212
|
+
GROUP BY query
|
|
213
|
+
HAVING prior_clicks > 0
|
|
214
|
+
ORDER BY click_change ASC
|
|
215
|
+
LIMIT ?
|
|
216
|
+
`, [
|
|
217
|
+
current.startDate, current.endDate,
|
|
218
|
+
prior.startDate, prior.endDate,
|
|
219
|
+
current.startDate, current.endDate,
|
|
220
|
+
prior.startDate, prior.endDate,
|
|
221
|
+
current.startDate, current.endDate,
|
|
222
|
+
prior.startDate, prior.endDate,
|
|
223
|
+
prior.startDate, prior.endDate,
|
|
224
|
+
current.startDate, current.endDate,
|
|
225
|
+
prior.startDate, prior.endDate,
|
|
226
|
+
current.startDate, current.endDate,
|
|
227
|
+
prior.startDate, prior.endDate,
|
|
228
|
+
...fv,
|
|
229
|
+
limit,
|
|
230
|
+
]);
|
|
231
|
+
return { insight: 'declining_queries', dateRange: { current, prior }, rows };
|
|
232
|
+
},
|
|
233
|
+
growing_pages: (db, params, current, prior) => {
|
|
234
|
+
const limit = params.limit || 50;
|
|
235
|
+
const f = filterSQL(params);
|
|
236
|
+
const fv = filterValues(params);
|
|
237
|
+
const rows = db.query(`
|
|
238
|
+
SELECT page,
|
|
239
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as current_clicks,
|
|
240
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as prior_clicks,
|
|
241
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END)
|
|
242
|
+
- SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as click_change,
|
|
243
|
+
ROUND(
|
|
244
|
+
(SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END)
|
|
245
|
+
- SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END))
|
|
246
|
+
* 100.0
|
|
247
|
+
/ NULLIF(SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END), 0),
|
|
248
|
+
1
|
|
249
|
+
) as pct_change
|
|
250
|
+
FROM search_analytics
|
|
251
|
+
WHERE page IS NOT NULL
|
|
252
|
+
AND (date BETWEEN ? AND ? OR date BETWEEN ? AND ?)${f}
|
|
253
|
+
GROUP BY page
|
|
254
|
+
HAVING current_clicks > 0
|
|
255
|
+
ORDER BY click_change DESC
|
|
256
|
+
LIMIT ?
|
|
257
|
+
`, [
|
|
258
|
+
current.startDate, current.endDate,
|
|
259
|
+
prior.startDate, prior.endDate,
|
|
260
|
+
current.startDate, current.endDate,
|
|
261
|
+
prior.startDate, prior.endDate,
|
|
262
|
+
current.startDate, current.endDate,
|
|
263
|
+
prior.startDate, prior.endDate,
|
|
264
|
+
prior.startDate, prior.endDate,
|
|
265
|
+
current.startDate, current.endDate,
|
|
266
|
+
prior.startDate, prior.endDate,
|
|
267
|
+
...fv,
|
|
268
|
+
limit,
|
|
269
|
+
]);
|
|
270
|
+
return { insight: 'growing_pages', dateRange: { current, prior }, rows };
|
|
271
|
+
},
|
|
272
|
+
declining_pages: (db, params, current, prior) => {
|
|
273
|
+
const limit = params.limit || 50;
|
|
274
|
+
const f = filterSQL(params);
|
|
275
|
+
const fv = filterValues(params);
|
|
276
|
+
const rows = db.query(`
|
|
277
|
+
SELECT page,
|
|
278
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as current_clicks,
|
|
279
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as prior_clicks,
|
|
280
|
+
SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END)
|
|
281
|
+
- SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END) as click_change,
|
|
282
|
+
ROUND(
|
|
283
|
+
(SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END)
|
|
284
|
+
- SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END))
|
|
285
|
+
* 100.0
|
|
286
|
+
/ NULLIF(SUM(CASE WHEN date BETWEEN ? AND ? THEN clicks ELSE 0 END), 0),
|
|
287
|
+
1
|
|
288
|
+
) as pct_change
|
|
289
|
+
FROM search_analytics
|
|
290
|
+
WHERE page IS NOT NULL
|
|
291
|
+
AND (date BETWEEN ? AND ? OR date BETWEEN ? AND ?)${f}
|
|
292
|
+
GROUP BY page
|
|
293
|
+
HAVING prior_clicks > 0
|
|
294
|
+
ORDER BY click_change ASC
|
|
295
|
+
LIMIT ?
|
|
296
|
+
`, [
|
|
297
|
+
current.startDate, current.endDate,
|
|
298
|
+
prior.startDate, prior.endDate,
|
|
299
|
+
current.startDate, current.endDate,
|
|
300
|
+
prior.startDate, prior.endDate,
|
|
301
|
+
current.startDate, current.endDate,
|
|
302
|
+
prior.startDate, prior.endDate,
|
|
303
|
+
prior.startDate, prior.endDate,
|
|
304
|
+
current.startDate, current.endDate,
|
|
305
|
+
prior.startDate, prior.endDate,
|
|
306
|
+
...fv,
|
|
307
|
+
limit,
|
|
308
|
+
]);
|
|
309
|
+
return { insight: 'declining_pages', dateRange: { current, prior }, rows };
|
|
310
|
+
},
|
|
311
|
+
opportunities: (db, params, current, _prior) => {
|
|
312
|
+
const limit = params.limit || 50;
|
|
313
|
+
const minImpressions = params.minImpressions || 100;
|
|
314
|
+
const f = filterSQL(params);
|
|
315
|
+
const fv = filterValues(params);
|
|
316
|
+
const rows = db.query(`
|
|
317
|
+
SELECT query,
|
|
318
|
+
SUM(clicks) as clicks,
|
|
319
|
+
SUM(impressions) as impressions,
|
|
320
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
321
|
+
ROUND(AVG(position), 1) as avg_position
|
|
322
|
+
FROM search_analytics
|
|
323
|
+
WHERE date BETWEEN ? AND ? AND query IS NOT NULL${f}
|
|
324
|
+
GROUP BY query
|
|
325
|
+
HAVING avg_position BETWEEN 4 AND 20
|
|
326
|
+
AND impressions > ?
|
|
327
|
+
ORDER BY impressions DESC
|
|
328
|
+
LIMIT ?
|
|
329
|
+
`, [current.startDate, current.endDate, ...fv, minImpressions, limit]);
|
|
330
|
+
return { insight: 'opportunities', dateRange: current, rows };
|
|
331
|
+
},
|
|
332
|
+
device_breakdown: (db, params, current, _prior) => {
|
|
333
|
+
const f = filterSQL(params);
|
|
334
|
+
const fv = filterValues(params);
|
|
335
|
+
const rows = db.query(`
|
|
336
|
+
SELECT device,
|
|
337
|
+
SUM(clicks) as clicks,
|
|
338
|
+
SUM(impressions) as impressions,
|
|
339
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
340
|
+
ROUND(AVG(position), 1) as avg_position
|
|
341
|
+
FROM search_analytics
|
|
342
|
+
WHERE date BETWEEN ? AND ?${f}
|
|
343
|
+
GROUP BY device
|
|
344
|
+
ORDER BY clicks DESC
|
|
345
|
+
`, [current.startDate, current.endDate, ...fv]);
|
|
346
|
+
return { insight: 'device_breakdown', dateRange: current, rows };
|
|
347
|
+
},
|
|
348
|
+
country_breakdown: (db, params, current, _prior) => {
|
|
349
|
+
const limit = params.limit || 50;
|
|
350
|
+
const f = filterSQL(params);
|
|
351
|
+
const fv = filterValues(params);
|
|
352
|
+
const rows = db.query(`
|
|
353
|
+
SELECT country,
|
|
354
|
+
SUM(clicks) as clicks,
|
|
355
|
+
SUM(impressions) as impressions,
|
|
356
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
357
|
+
ROUND(AVG(position), 1) as avg_position
|
|
358
|
+
FROM search_analytics
|
|
359
|
+
WHERE date BETWEEN ? AND ?${f}
|
|
360
|
+
GROUP BY country
|
|
361
|
+
ORDER BY clicks DESC
|
|
362
|
+
LIMIT ?
|
|
363
|
+
`, [current.startDate, current.endDate, ...fv, limit]);
|
|
364
|
+
return { insight: 'country_breakdown', dateRange: current, rows };
|
|
365
|
+
},
|
|
366
|
+
page_queries: (db, params, current, _prior) => {
|
|
367
|
+
const limit = params.limit || 50;
|
|
368
|
+
if (!params.pageFilter) {
|
|
369
|
+
throw new Error('page_queries insight requires the "pageFilter" parameter.');
|
|
370
|
+
}
|
|
371
|
+
const fv = [];
|
|
372
|
+
let extraFilter = '';
|
|
373
|
+
if (params.device) {
|
|
374
|
+
extraFilter += ' AND device = ?';
|
|
375
|
+
fv.push(params.device);
|
|
376
|
+
}
|
|
377
|
+
if (params.country) {
|
|
378
|
+
extraFilter += ' AND country = ?';
|
|
379
|
+
fv.push(params.country);
|
|
380
|
+
}
|
|
381
|
+
const rows = db.query(`
|
|
382
|
+
SELECT query,
|
|
383
|
+
SUM(clicks) as clicks,
|
|
384
|
+
SUM(impressions) as impressions,
|
|
385
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
386
|
+
ROUND(AVG(position), 1) as avg_position
|
|
387
|
+
FROM search_analytics
|
|
388
|
+
WHERE page LIKE ? AND date BETWEEN ? AND ? AND query IS NOT NULL${extraFilter}
|
|
389
|
+
GROUP BY query
|
|
390
|
+
ORDER BY clicks DESC
|
|
391
|
+
LIMIT ?
|
|
392
|
+
`, [`%${params.pageFilter}%`, current.startDate, current.endDate, ...fv, limit]);
|
|
393
|
+
return { insight: 'page_queries', dateRange: current, pageFilter: params.pageFilter, rows };
|
|
394
|
+
},
|
|
395
|
+
query_pages: (db, params, current, _prior) => {
|
|
396
|
+
const limit = params.limit || 50;
|
|
397
|
+
if (!params.queryFilter) {
|
|
398
|
+
throw new Error('query_pages insight requires the "queryFilter" parameter.');
|
|
399
|
+
}
|
|
400
|
+
const fv = [];
|
|
401
|
+
let extraFilter = '';
|
|
402
|
+
if (params.device) {
|
|
403
|
+
extraFilter += ' AND device = ?';
|
|
404
|
+
fv.push(params.device);
|
|
405
|
+
}
|
|
406
|
+
if (params.country) {
|
|
407
|
+
extraFilter += ' AND country = ?';
|
|
408
|
+
fv.push(params.country);
|
|
409
|
+
}
|
|
410
|
+
const rows = db.query(`
|
|
411
|
+
SELECT page,
|
|
412
|
+
SUM(clicks) as clicks,
|
|
413
|
+
SUM(impressions) as impressions,
|
|
414
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
415
|
+
ROUND(AVG(position), 1) as avg_position
|
|
416
|
+
FROM search_analytics
|
|
417
|
+
WHERE query = ? AND date BETWEEN ? AND ? AND page IS NOT NULL${extraFilter}
|
|
418
|
+
GROUP BY page
|
|
419
|
+
ORDER BY avg_position ASC
|
|
420
|
+
LIMIT ?
|
|
421
|
+
`, [params.queryFilter, current.startDate, current.endDate, ...fv, limit]);
|
|
422
|
+
return { insight: 'query_pages', dateRange: current, queryFilter: params.queryFilter, rows };
|
|
423
|
+
},
|
|
424
|
+
daily_trend: (db, params, current, _prior) => {
|
|
425
|
+
const f = filterSQL(params);
|
|
426
|
+
const fv = filterValues(params);
|
|
427
|
+
const rows = db.query(`
|
|
428
|
+
SELECT date,
|
|
429
|
+
SUM(clicks) as clicks,
|
|
430
|
+
SUM(impressions) as impressions
|
|
431
|
+
FROM search_analytics
|
|
432
|
+
WHERE date BETWEEN ? AND ?${f}
|
|
433
|
+
GROUP BY date
|
|
434
|
+
ORDER BY date ASC
|
|
435
|
+
`, [current.startDate, current.endDate, ...fv]);
|
|
436
|
+
return { insight: 'daily_trend', dateRange: current, rows };
|
|
437
|
+
},
|
|
438
|
+
new_queries: (db, params, current, prior) => {
|
|
439
|
+
const limit = params.limit || 50;
|
|
440
|
+
const f = filterSQL(params);
|
|
441
|
+
const fv = filterValues(params);
|
|
442
|
+
const rows = db.query(`
|
|
443
|
+
SELECT query,
|
|
444
|
+
SUM(clicks) as clicks,
|
|
445
|
+
SUM(impressions) as impressions,
|
|
446
|
+
ROUND(AVG(position), 1) as avg_position
|
|
447
|
+
FROM search_analytics
|
|
448
|
+
WHERE date BETWEEN ? AND ?
|
|
449
|
+
AND query IS NOT NULL${f}
|
|
450
|
+
AND query IN (
|
|
451
|
+
SELECT query FROM search_analytics WHERE date BETWEEN ? AND ? AND query IS NOT NULL
|
|
452
|
+
EXCEPT
|
|
453
|
+
SELECT query FROM search_analytics WHERE date BETWEEN ? AND ? AND query IS NOT NULL
|
|
454
|
+
)
|
|
455
|
+
GROUP BY query
|
|
456
|
+
ORDER BY impressions DESC
|
|
457
|
+
LIMIT ?
|
|
458
|
+
`, [current.startDate, current.endDate, ...fv, current.startDate, current.endDate, prior.startDate, prior.endDate, limit]);
|
|
459
|
+
return { insight: 'new_queries', dateRange: { current, prior }, rows };
|
|
460
|
+
},
|
|
461
|
+
lost_queries: (db, params, current, prior) => {
|
|
462
|
+
const limit = params.limit || 50;
|
|
463
|
+
const f = filterSQL(params);
|
|
464
|
+
const fv = filterValues(params);
|
|
465
|
+
const rows = db.query(`
|
|
466
|
+
SELECT query,
|
|
467
|
+
SUM(clicks) as clicks,
|
|
468
|
+
SUM(impressions) as impressions,
|
|
469
|
+
ROUND(AVG(position), 1) as avg_position
|
|
470
|
+
FROM search_analytics
|
|
471
|
+
WHERE date BETWEEN ? AND ?
|
|
472
|
+
AND query IS NOT NULL${f}
|
|
473
|
+
AND query IN (
|
|
474
|
+
SELECT query FROM search_analytics WHERE date BETWEEN ? AND ? AND query IS NOT NULL
|
|
475
|
+
EXCEPT
|
|
476
|
+
SELECT query FROM search_analytics WHERE date BETWEEN ? AND ? AND query IS NOT NULL
|
|
477
|
+
)
|
|
478
|
+
GROUP BY query
|
|
479
|
+
ORDER BY clicks DESC
|
|
480
|
+
LIMIT ?
|
|
481
|
+
`, [prior.startDate, prior.endDate, ...fv, prior.startDate, prior.endDate, current.startDate, current.endDate, limit]);
|
|
482
|
+
return { insight: 'lost_queries', dateRange: { current, prior }, rows };
|
|
483
|
+
},
|
|
484
|
+
branded_split: (db, params, current, _prior) => {
|
|
485
|
+
if (!params.brandTerms || params.brandTerms.length === 0) {
|
|
486
|
+
throw new Error('branded_split insight requires the "brandTerms" parameter (array of brand terms).');
|
|
487
|
+
}
|
|
488
|
+
const f = filterSQL(params);
|
|
489
|
+
const fv = filterValues(params);
|
|
490
|
+
// Build CASE expression for brand matching
|
|
491
|
+
const brandConditions = params.brandTerms
|
|
492
|
+
.map(() => 'LOWER(query) LIKE ?')
|
|
493
|
+
.join(' OR ');
|
|
494
|
+
const brandValues = params.brandTerms.map((t) => `%${t.toLowerCase()}%`);
|
|
495
|
+
const rows = db.query(`
|
|
496
|
+
SELECT
|
|
497
|
+
CASE WHEN (${brandConditions}) THEN 'branded' ELSE 'non-branded' END as segment,
|
|
498
|
+
SUM(clicks) as clicks,
|
|
499
|
+
SUM(impressions) as impressions,
|
|
500
|
+
ROUND(CAST(SUM(clicks) AS REAL) / NULLIF(SUM(impressions), 0), 4) as ctr,
|
|
501
|
+
ROUND(AVG(position), 1) as avg_position
|
|
502
|
+
FROM search_analytics
|
|
503
|
+
WHERE date BETWEEN ? AND ? AND query IS NOT NULL${f}
|
|
504
|
+
GROUP BY segment
|
|
505
|
+
`, [...brandValues, current.startDate, current.endDate, ...fv]);
|
|
506
|
+
return { insight: 'branded_split', dateRange: current, brandTerms: params.brandTerms, rows };
|
|
507
|
+
},
|
|
508
|
+
};
|
|
509
|
+
//# sourceMappingURL=get-insights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-insights.js","sourceRoot":"","sources":["../../src/tools/get-insights.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { GscClient } from '../core/GscClient.js';
|
|
2
|
+
export interface OverviewParams {
|
|
3
|
+
dateRange?: string;
|
|
4
|
+
sortBy?: 'alpha' | 'clicks' | 'impressions' | 'ctr' | 'position';
|
|
5
|
+
search?: string;
|
|
6
|
+
}
|
|
7
|
+
interface PropertyOverview {
|
|
8
|
+
siteUrl: string;
|
|
9
|
+
domain: string;
|
|
10
|
+
lastSyncedAt: string | null;
|
|
11
|
+
current: {
|
|
12
|
+
clicks: number;
|
|
13
|
+
impressions: number;
|
|
14
|
+
ctr: number;
|
|
15
|
+
avgPosition: number | null;
|
|
16
|
+
};
|
|
17
|
+
changes: {
|
|
18
|
+
clicksPct: number | null;
|
|
19
|
+
impressionsPct: number | null;
|
|
20
|
+
ctrPct: number | null;
|
|
21
|
+
avgPositionPct: number | null;
|
|
22
|
+
};
|
|
23
|
+
sparkline: Array<{
|
|
24
|
+
date: string;
|
|
25
|
+
clicks: number;
|
|
26
|
+
impressions: number;
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
interface OverviewData {
|
|
30
|
+
dateRange: string;
|
|
31
|
+
sortBy: string;
|
|
32
|
+
properties: PropertyOverview[];
|
|
33
|
+
}
|
|
34
|
+
export declare function getOverviewData(gscClient: GscClient, params: OverviewParams): Promise<OverviewData>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=get-overview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-overview.d.ts","sourceRoot":"","sources":["../../src/tools/get-overview.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,aAAa,GAAG,KAAK,GAAG,UAAU,CAAC;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,gBAAgB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,MAAM,CAAC;QACpB,GAAG,EAAE,MAAM,CAAC;QACZ,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;IACF,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CAAC;IACF,SAAS,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzE;AAED,UAAU,YAAY;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,YAAY,CAAC,CAoHvB"}
|