(input: {
projectId: string;
startDate: string;
endDate: string;
conversionEvent: string;
windowHours?: number;
limit?: number;
})
| 268 | } |
| 269 | |
| 270 | export async function getPageConversionsCore(input: { |
| 271 | projectId: string; |
| 272 | startDate: string; |
| 273 | endDate: string; |
| 274 | conversionEvent: string; |
| 275 | windowHours?: number; |
| 276 | limit?: number; |
| 277 | }): Promise<IPageConversionRow[]> { |
| 278 | const { projectId, startDate, endDate, conversionEvent, windowHours = 24, limit = 100 } = input; |
| 279 | const sql = ` |
| 280 | WITH |
| 281 | conversion_events AS ( |
| 282 | SELECT profile_id, created_at AS conv_time |
| 283 | FROM events |
| 284 | WHERE project_id = ${sqlstring.escape(projectId)} |
| 285 | AND name = ${sqlstring.escape(conversionEvent)} |
| 286 | AND created_at BETWEEN toDateTime(${sqlstring.escape(startDate)}) AND toDateTime(${sqlstring.escape(endDate)}) |
| 287 | ), |
| 288 | views_before_conversions AS ( |
| 289 | SELECT DISTINCT e.profile_id, e.path, e.origin |
| 290 | FROM events AS e |
| 291 | INNER JOIN conversion_events AS c ON e.profile_id = c.profile_id |
| 292 | WHERE e.project_id = ${sqlstring.escape(projectId)} |
| 293 | AND e.name = 'screen_view' |
| 294 | AND e.path != '' |
| 295 | AND e.created_at BETWEEN toDateTime(${sqlstring.escape(startDate)}) AND toDateTime(${sqlstring.escape(endDate)}) |
| 296 | AND e.created_at < c.conv_time |
| 297 | AND e.created_at >= c.conv_time - INTERVAL ${Number(windowHours)} HOUR |
| 298 | ), |
| 299 | total_visitors AS ( |
| 300 | SELECT path, origin, uniq(session_id) AS visitors |
| 301 | FROM events |
| 302 | WHERE project_id = ${sqlstring.escape(projectId)} |
| 303 | AND name = 'screen_view' |
| 304 | AND path != '' |
| 305 | AND created_at BETWEEN toDateTime(${sqlstring.escape(startDate)}) AND toDateTime(${sqlstring.escape(endDate)}) |
| 306 | GROUP BY path, origin |
| 307 | ) |
| 308 | SELECT |
| 309 | vbc.path, |
| 310 | vbc.origin, |
| 311 | count() AS unique_converters, |
| 312 | any(tv.visitors) AS total_visitors, |
| 313 | round(100.0 * count() / any(tv.visitors), 2) AS conversion_rate |
| 314 | FROM views_before_conversions AS vbc |
| 315 | LEFT JOIN total_visitors AS tv ON vbc.path = tv.path AND vbc.origin = tv.origin |
| 316 | GROUP BY vbc.path, vbc.origin |
| 317 | ORDER BY unique_converters DESC |
| 318 | LIMIT ${Number(limit)} |
| 319 | `; |
| 320 | return chQuery<IPageConversionRow>(sql); |
| 321 | } |
no test coverage detected