mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-11 16:28:37 +01:00
new selfhosted version
This commit is contained in:
153
dashboard/server/services/ai/plugins/BouncingRatePlugin.ts
Normal file
153
dashboard/server/services/ai/plugins/BouncingRatePlugin.ts
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
import { Types } from "mongoose";
|
||||
import { AiPlugin, getFirstAvailableSliceFromDates } from "../Plugin";
|
||||
import { VisitModel } from "~/shared/schema/metrics/VisitSchema";
|
||||
import { prepareTimelineAggregation } from "../../TimelineService";
|
||||
|
||||
const getBouncingRatePlugin = new AiPlugin<'getBouncingRate', ['from', 'to', 'domain', 'limit']>('getBouncingRate',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getBouncingRate',
|
||||
description: 'Gets an array of bouncing rate in the user website on a date range.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific webdomain/website' },
|
||||
limit: { type: 'number', description: 'Max number of items to return' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
|
||||
const info = prepareTimelineAggregation({
|
||||
model: VisitModel,
|
||||
projectId: new Types.ObjectId(data.project_id),
|
||||
from: new Date(data.from).getTime(),
|
||||
to: new Date(data.to).getTime(),
|
||||
slice: getFirstAvailableSliceFromDates(data.from, data.to),
|
||||
domain: data.domain,
|
||||
});
|
||||
|
||||
const aggregation = [
|
||||
{
|
||||
$match: {
|
||||
project_id: new Types.ObjectId(data.project_id),
|
||||
created_at: {
|
||||
$gte: new Date(data.from),
|
||||
$lte: new Date(data.to)
|
||||
},
|
||||
...info.domainMatch,
|
||||
}
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
created_at: 1, session: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
date: {
|
||||
$dateTrunc: {
|
||||
date: "$created_at",
|
||||
unit: info.granularity,
|
||||
timezone: "UTC"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: {
|
||||
date: "$date",
|
||||
session: "$session"
|
||||
},
|
||||
pageViews: {
|
||||
$sum: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: {
|
||||
date: "$_id.date"
|
||||
},
|
||||
totalSessions: {
|
||||
$sum: 1
|
||||
},
|
||||
bouncedSessions: {
|
||||
$sum: { $cond: [{ $eq: ["$pageViews", 1] }, 1, 0] }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
_id: 1,
|
||||
totalSessions: 1,
|
||||
bouncedSessions: 1,
|
||||
bounceRate: {
|
||||
$cond: [{ $eq: ["$totalSessions", 0] }, 0,
|
||||
{
|
||||
$multiply: [
|
||||
{
|
||||
$divide: [
|
||||
"$bouncedSessions",
|
||||
"$totalSessions"
|
||||
]
|
||||
},
|
||||
100
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
$densify: {
|
||||
field: "_id.date",
|
||||
range: {
|
||||
step: 1,
|
||||
unit: info.granularity,
|
||||
bounds: [
|
||||
info.from,
|
||||
info.to
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
timestamp: {
|
||||
$toLong: "$_id.date"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
count: {
|
||||
$ifNull: ["$bounceRate", 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
$sort: {
|
||||
"_id.date": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
$project: { _id: 1, count: 1, timestamp: 1 }
|
||||
}
|
||||
] as any[];
|
||||
const result = await VisitModel.aggregate(aggregation, { allowDiskUse: true });
|
||||
return result;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export const bouncingRatePlugins = [
|
||||
getBouncingRatePlugin
|
||||
]
|
||||
63
dashboard/server/services/ai/plugins/ChartPlugin.ts
Normal file
63
dashboard/server/services/ai/plugins/ChartPlugin.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { AiPlugin } from "../Plugin";
|
||||
|
||||
const createChartPlugin = new AiPlugin<'createChart', ['labels', 'title', 'datasets']>('createChart',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'createChart',
|
||||
description: 'Creates a chart based on the provided datasets. Used to show a visual rappresentation of data to the user.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
labels: {
|
||||
type: 'array',
|
||||
items: { type: 'string' },
|
||||
description: 'Labels for each data point in the chart'
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
description: 'Title of the chart to let user understand what is displaying, not include dates'
|
||||
},
|
||||
datasets: {
|
||||
type: 'array',
|
||||
description: 'List of datasets',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
chartType: {
|
||||
type: 'string',
|
||||
enum: ['line', 'bar'],
|
||||
description: 'The type of chart to display the dataset, either "line" or "bar"'
|
||||
},
|
||||
points: {
|
||||
type: 'array',
|
||||
items: { type: 'number' },
|
||||
description: 'Numerical values for each data point in the chart'
|
||||
},
|
||||
color: {
|
||||
type: 'string',
|
||||
description: 'Color used to represent the dataset in format "#RRGGBB"'
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Name of the dataset'
|
||||
}
|
||||
},
|
||||
required: ['points', 'chartType', 'name'],
|
||||
description: 'Data points and style information for the dataset'
|
||||
}
|
||||
}
|
||||
},
|
||||
required: ['labels', 'datasets', 'title']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
return { ok: true, chart: true }
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export const chartPlugins = [
|
||||
createChartPlugin
|
||||
]
|
||||
253
dashboard/server/services/ai/plugins/DataPlugin.ts
Normal file
253
dashboard/server/services/ai/plugins/DataPlugin.ts
Normal file
@@ -0,0 +1,253 @@
|
||||
import { Types } from "mongoose";
|
||||
import { AiPlugin } from "../Plugin";
|
||||
import { VisitModel } from "~/shared/schema/metrics/VisitSchema";
|
||||
import { getDomainFromString } from "~/server/utils/getRequestContext";
|
||||
|
||||
const getReferrersPlugin = new AiPlugin<'getReferrers', ['from', 'to', 'domain', 'limit']>('getReferrers',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getReferrers',
|
||||
description: 'Gets an array of website referrers (visit sources) on a date range.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific webdomain/website' },
|
||||
limit: { type: 'number', description: 'Max number of items to return' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
|
||||
const result = await VisitModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
project_id: new Types.ObjectId(data.project_id),
|
||||
created_at: {
|
||||
$gte: new Date(data.from),
|
||||
$lte: new Date(data.to)
|
||||
},
|
||||
website: getDomainFromString(data.domain ?? '*') ?? { $ne: null },
|
||||
}
|
||||
},
|
||||
{ $group: { _id: "$referrer", count: { $sum: 1, } } },
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: Math.min(data.limit ?? 500, 500) }
|
||||
]);
|
||||
|
||||
return result as { _id: string, count: number }[];
|
||||
}
|
||||
);
|
||||
|
||||
const getContinentsPlugin = new AiPlugin<'getContinents', ['from', 'to', 'domain', 'limit']>('getContinents',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getContinents',
|
||||
description: 'Gets an array of continents that visited the user website on a date range.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific webdomain/website' },
|
||||
limit: { type: 'number', description: 'Max number of items to return' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
|
||||
const result = await VisitModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
project_id: new Types.ObjectId(data.project_id),
|
||||
created_at: {
|
||||
$gte: new Date(data.from),
|
||||
$lte: new Date(data.to)
|
||||
},
|
||||
website: getDomainFromString(data.domain ?? '*') ?? { $ne: null },
|
||||
}
|
||||
},
|
||||
{ $group: { _id: "$continent", count: { $sum: 1, } } },
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: Math.min(data.limit ?? 500, 500) }
|
||||
]);
|
||||
|
||||
return result as { _id: string, count: number }[];
|
||||
}
|
||||
);
|
||||
|
||||
const getCountriesPlugin = new AiPlugin<'getCountries', ['from', 'to', 'domain', 'limit']>('getCountries',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getCountries',
|
||||
description: 'Gets an array of countries that visited the user website on a date range.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific webdomain/website' },
|
||||
limit: { type: 'number', description: 'Max number of items to return' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
|
||||
const result = await VisitModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
project_id: new Types.ObjectId(data.project_id),
|
||||
created_at: {
|
||||
$gte: new Date(data.from),
|
||||
$lte: new Date(data.to)
|
||||
},
|
||||
website: getDomainFromString(data.domain ?? '*') ?? { $ne: null },
|
||||
}
|
||||
},
|
||||
{ $group: { _id: "$country", count: { $sum: 1, } } },
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: Math.min(data.limit ?? 500, 500) }
|
||||
]);
|
||||
|
||||
return result as { _id: string, count: number }[];
|
||||
}
|
||||
);
|
||||
|
||||
const getPagesPlugin = new AiPlugin<'getPages', ['from', 'to', 'domain', 'limit']>('getPages',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getPages',
|
||||
description: 'Gets an array of most visited pages on a date range.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific webdomain/website' },
|
||||
limit: { type: 'number', description: 'Max number of items to return' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
|
||||
const result = await VisitModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
project_id: new Types.ObjectId(data.project_id),
|
||||
created_at: {
|
||||
$gte: new Date(data.from),
|
||||
$lte: new Date(data.to)
|
||||
},
|
||||
website: getDomainFromString(data.domain ?? '*') ?? { $ne: null },
|
||||
}
|
||||
},
|
||||
{ $group: { _id: "$page", count: { $sum: 1, } } },
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: Math.min(data.limit ?? 500, 500) }
|
||||
]);
|
||||
|
||||
return result as { _id: string, count: number }[];
|
||||
}
|
||||
);
|
||||
|
||||
const getBrowsersPlugin = new AiPlugin<'getBrowsers', ['from', 'to', 'domain', 'limit']>('getBrowsers',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getBrowsers',
|
||||
description: 'Gets an array of browsers that visited the user website on a date range.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific webdomain/website' },
|
||||
limit: { type: 'number', description: 'Max number of items to return' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
|
||||
const result = await VisitModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
project_id: new Types.ObjectId(data.project_id),
|
||||
created_at: {
|
||||
$gte: new Date(data.from),
|
||||
$lte: new Date(data.to)
|
||||
},
|
||||
website: getDomainFromString(data.domain ?? '*') ?? { $ne: null },
|
||||
}
|
||||
},
|
||||
{ $group: { _id: "$browser", count: { $sum: 1, } } },
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: Math.min(data.limit ?? 500, 500) }
|
||||
]);
|
||||
|
||||
return result as { _id: string, count: number }[];
|
||||
}
|
||||
);
|
||||
|
||||
const getDevicesPlugin = new AiPlugin<'getDevices', ['from', 'to', 'domain', 'limit']>('getDevices',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getDevices',
|
||||
description: 'Gets an array of devices that visited the user website on a date range.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific webdomain/website' },
|
||||
limit: { type: 'number', description: 'Max number of items to return' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
|
||||
const result = await VisitModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
project_id: new Types.ObjectId(data.project_id),
|
||||
created_at: {
|
||||
$gte: new Date(data.from),
|
||||
$lte: new Date(data.to)
|
||||
},
|
||||
website: getDomainFromString(data.domain ?? '*') ?? { $ne: null },
|
||||
}
|
||||
},
|
||||
{ $group: { _id: "$device", count: { $sum: 1, } } },
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: Math.min(data.limit ?? 500, 500) }
|
||||
]);
|
||||
|
||||
return result as { _id: string, count: number }[];
|
||||
}
|
||||
);
|
||||
|
||||
export const dataPlugins = [
|
||||
getReferrersPlugin,
|
||||
getContinentsPlugin,
|
||||
getCountriesPlugin,
|
||||
getPagesPlugin,
|
||||
getBrowsersPlugin,
|
||||
getDevicesPlugin
|
||||
]
|
||||
52
dashboard/server/services/ai/plugins/SessionsPlugin.ts
Normal file
52
dashboard/server/services/ai/plugins/SessionsPlugin.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { executeAdvancedTimelineAggregation } from "../../TimelineService";
|
||||
import { Types } from "mongoose";
|
||||
import { AiPlugin, getFirstAvailableSliceFromDates } from "../Plugin";
|
||||
import { VisitModel } from "~/shared/schema/metrics/VisitSchema";
|
||||
|
||||
const getSessionsTimelinePlugin = new AiPlugin<'getSessionsTimeline', ['from', 'to', 'page', 'domain']>(
|
||||
'getSessionsTimeline',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getSessionsTimeline',
|
||||
description: 'Gets an array of date and count for sessions (unique visitors) received on a date range.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
page: { type: 'string', description: 'The page of the visit' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific domain/website' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
const timelineData = await executeAdvancedTimelineAggregation({
|
||||
projectId: new Types.ObjectId(data.project_id),
|
||||
model: VisitModel,
|
||||
from: new Date(data.from).getTime(),
|
||||
to: new Date(data.to).getTime(),
|
||||
slice: getFirstAvailableSliceFromDates(data.from, data.to),
|
||||
domain: data.domain,
|
||||
customIdGroup: { count: '$session' },
|
||||
customQueries: [
|
||||
{
|
||||
index: 2,
|
||||
query: {
|
||||
$group: { _id: { date: '$_id.date' }, count: { $sum: 1 } }
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
return timelineData;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
export const sessionsPlugins = [
|
||||
getSessionsTimelinePlugin
|
||||
]
|
||||
66
dashboard/server/services/ai/plugins/UTMData.ts
Normal file
66
dashboard/server/services/ai/plugins/UTMData.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { Types } from "mongoose";
|
||||
import { AiPlugin } from "../Plugin";
|
||||
import { VisitModel } from "~/shared/schema/metrics/VisitSchema";
|
||||
import { getDomainFromString } from "~/server/utils/getRequestContext";
|
||||
import { UtmKey } from "~/components/complex/line-data/selectors/SelectRefer.vue";
|
||||
|
||||
|
||||
|
||||
const utmKeys = ["utm_medium", "utm_source", "utm_term", "utm_campaign", "utm_content"]
|
||||
|
||||
const plugins: AiPlugin[] = []
|
||||
|
||||
for (const utmKey of utmKeys) {
|
||||
|
||||
const getUtmPlugin = new AiPlugin<`get_${typeof utmKey}`, ['domain', 'from', 'to', 'limit']>(`get_${utmKey}`,
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: `get_${utmKey}`,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific webdomain/website' },
|
||||
limit: { type: 'number', description: 'Max number of items to return' }
|
||||
},
|
||||
required: ['from', 'to']
|
||||
},
|
||||
description: `Gets an array of all the ${utmKey} of the visits in a date range`,
|
||||
}
|
||||
},
|
||||
async ({ domain, from, to, project_id, limit }) => {
|
||||
|
||||
const websiteMatch = domain ? { website: domain } : {};
|
||||
|
||||
const result = await VisitModel.aggregate([
|
||||
{
|
||||
$match: {
|
||||
project_id: new Types.ObjectId(project_id),
|
||||
created_at: { $gte: new Date(from), $lte: new Date(to) },
|
||||
...websiteMatch,
|
||||
[utmKey]: { $ne: null }
|
||||
}
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: `$${utmKey}`,
|
||||
count: { $sum: 1 }
|
||||
}
|
||||
},
|
||||
{ $sort: { count: -1 } },
|
||||
{ $limit: Math.min(limit ?? 500, 500) }
|
||||
]);
|
||||
|
||||
|
||||
return result as { _id: string, count: number }[];
|
||||
|
||||
});
|
||||
|
||||
plugins.push(getUtmPlugin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const utmDataPlugins = plugins;
|
||||
58
dashboard/server/services/ai/plugins/VisitsPlugins.ts
Normal file
58
dashboard/server/services/ai/plugins/VisitsPlugins.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { executeAdvancedTimelineAggregation } from "../../TimelineService";
|
||||
import { Types } from "mongoose";
|
||||
import { getFirstAvailableSliceFromDates } from "../Plugin";
|
||||
import { AiPlugin } from "../Plugin";
|
||||
import { VisitModel } from "~/shared/schema/metrics/VisitSchema";
|
||||
|
||||
const getVisitsTimelinePlugin = new AiPlugin<'getVisitsTimeline', ['from', 'to', 'page', 'domain', 'continent', 'country', 'region', 'city', 'device']>(
|
||||
'getVisitsTimeline',
|
||||
{
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getVisitsTimeline',
|
||||
description: 'Gets an array of date and count for visits received on a date range. Can be filtered for domain, continent, country, region, city, devices.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
page: { type: 'string', description: 'The page of the visit' },
|
||||
domain: { type: 'string', description: 'Used only to filter a specific domain/website' },
|
||||
device: { type: 'string', description: 'Used only to filter a specific device' },
|
||||
continent: { type: 'string', description: 'Used only to filter a specific continent - 2 letters' },
|
||||
country: { type: 'string', description: 'Used only to filter a specific country - 2 letters' },
|
||||
region: { type: 'string', description: 'Used only to filter a specific region - 2 letters' },
|
||||
city: { type: 'string', description: 'Used only to filter a specific city - 2 letters' },
|
||||
},
|
||||
required: ['from', 'to']
|
||||
}
|
||||
}
|
||||
},
|
||||
async (data) => {
|
||||
|
||||
const match: Record<string, string> = {}
|
||||
|
||||
if (data.device) match.device = data.device;
|
||||
if (data.continent) match.continent = data.continent;
|
||||
if (data.country) match.country = data.country;
|
||||
if (data.region) match.region = data.region;
|
||||
if (data.city) match.city = data.city;
|
||||
|
||||
const timelineData = await executeAdvancedTimelineAggregation({
|
||||
projectId: new Types.ObjectId(data.project_id),
|
||||
model: VisitModel,
|
||||
from: new Date(data.from).getTime(),
|
||||
to: new Date(data.to).getTime(),
|
||||
slice: getFirstAvailableSliceFromDates(data.from, data.to),
|
||||
domain: data.domain,
|
||||
customMatch: match
|
||||
});
|
||||
|
||||
return timelineData;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
export const visitsPlugins = [
|
||||
getVisitsTimelinePlugin
|
||||
]
|
||||
Reference in New Issue
Block a user