diff --git a/package.json b/package.json index e9137d1..2398155 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,6 @@ "redis": "^4.7.0" }, "devDependencies": { - "globs": "^0.1.4" + "glob": "^0.1.4" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3929c9d..2833539 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -166,6 +166,12 @@ importers: specifier: ^5.4.5 version: 5.6.3 + scripts: + devDependencies: + glob: + specifier: ^11.0.0 + version: 11.0.0 + security: devDependencies: '@types/node': @@ -2519,6 +2525,11 @@ packages: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true + glob@11.0.0: + resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} + engines: {node: 20 || >=22} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -2908,6 +2919,10 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jackspeak@4.0.2: + resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} + engines: {node: 20 || >=22} + jiti@1.21.6: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true @@ -3135,6 +3150,10 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.0.2: + resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3224,6 +3243,10 @@ packages: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true + minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -3586,6 +3609,10 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + path-to-regexp@0.1.10: resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} @@ -7560,6 +7587,15 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 + glob@11.0.0: + dependencies: + foreground-child: 3.3.0 + jackspeak: 4.0.2 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -7966,6 +8002,10 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jackspeak@4.0.2: + dependencies: + '@isaacs/cliui': 8.0.2 + jiti@1.21.6: {} jiti@2.4.0: {} @@ -8226,6 +8266,8 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@11.0.2: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -8297,6 +8339,10 @@ snapshots: mini-svg-data-uri@1.4.4: {} + minimatch@10.0.1: + dependencies: + brace-expansion: 2.0.1 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -8826,6 +8872,11 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + path-scurry@2.0.0: + dependencies: + lru-cache: 11.0.2 + minipass: 7.1.2 + path-to-regexp@0.1.10: {} path-to-regexp@6.3.0: {} diff --git a/security/package.json b/security/package.json index 3327843..5425180 100644 --- a/security/package.json +++ b/security/package.json @@ -12,7 +12,7 @@ "dev": "node scripts/start_dev.js", "compile": "tsc", "build_project": "node ../scripts/build.js", - "build": "npm run compile && npm run build" + "build": "npm run compile && npm run build_project" }, "keywords": [], "author": "Emily", diff --git a/security/src/Aggregations.ts b/security/src/Aggregations.ts index b3e83ec..d03a323 100644 --- a/security/src/Aggregations.ts +++ b/security/src/Aggregations.ts @@ -2,9 +2,11 @@ import DateService, { Slice } from '@services/DateService'; import { Model, Types } from "mongoose"; -export async function getAggregation(model: Model, pid: Types.ObjectId, from: number, to: number, slice: Slice) { +export async function getDayAggregation(model: Model, pid: Types.ObjectId, from: number, to: number) { - const { group, sort, fromParts } = DateService.getQueryDateRange(slice); + const sort = { created_at: 1 }; + const group = { $dateToString: { format: "%Y-%m-%d", date: "$created_at" } }; + const fromParts = { year: { $year: "$created_at" }, month: { $month: "$created_at" }, day: { $dayOfMonth: "$created_at" } }; const result = model.aggregate([ { @@ -16,7 +18,7 @@ export async function getAggregation(model: Model, pid: Types.ObjectId, fro { $group: { _id: group, count: { $sum: 1 } } }, { $sort: sort }, { $project: { _id: { $dateFromParts: fromParts }, count: "$count" } } - ]); + ] as any); return result; diff --git a/security/src/AnomalyService.ts b/security/src/AnomalyService.ts index 1b16636..081a4f9 100644 --- a/security/src/AnomalyService.ts +++ b/security/src/AnomalyService.ts @@ -7,7 +7,7 @@ import { VisitModel } from '@schema/metrics/VisitSchema' import * as url from 'url'; import { ProjectModel } from "@schema/project/ProjectSchema"; -import { getAggregation } from "./Aggregations"; +import { getDayAggregation } from "./Aggregations"; type TAvgInput = { _id: string, count: number } @@ -75,9 +75,9 @@ export async function findAnomalies(project_id: string, callback: AnomalyCallbac const from = Date.now() - 1000 * 60 * 60 * 24 * 30; const to = Date.now() - 1000 * 60 * 60 * 24; - const visitsTimelineData = await getAggregation(VisitModel, pid, from, to, 'day'); + const visitsTimelineData = await getDayAggregation(VisitModel, pid, from, to); - const eventsTimelineData = await getAggregation(EventModel, pid, from, to, 'day'); + const eventsTimelineData = await getDayAggregation(EventModel, pid, from, to); const websites: { _id: string, count: number }[] = await VisitModel.aggregate([ diff --git a/shared/services/EmailService.ts b/shared/services/EmailService.ts index 06112d0..c5fbd42 100644 --- a/shared/services/EmailService.ts +++ b/shared/services/EmailService.ts @@ -19,7 +19,7 @@ class EmailService { async sendLimitEmail50(target: string, projectName: string) { try { const sendSmtpEmail = new SendSmtpEmail(); - sendSmtpEmail.subject = "You've reached 50% limit on Litlyx"; + sendSmtpEmail.subject = "⚡ You've reached 50% limit on Litlyx"; sendSmtpEmail.sender = { "name": "Litlyx", "email": "help@litlyx.com" }; sendSmtpEmail.to = [{ "email": target }]; @@ -38,7 +38,7 @@ class EmailService { async sendLimitEmail90(target: string, projectName: string) { try { const sendSmtpEmail = new SendSmtpEmail(); - sendSmtpEmail.subject = "You've reached 90% limit on Litlyx"; + sendSmtpEmail.subject = "⚡ You've reached 90% limit on Litlyx"; sendSmtpEmail.sender = { "name": "Litlyx", "email": "help@litlyx.com" }; sendSmtpEmail.to = [{ "email": target }]; sendSmtpEmail.htmlContent = LIMIT_90_EMAIL @@ -55,7 +55,7 @@ class EmailService { async sendLimitEmailMax(target: string, projectName: string) { try { const sendSmtpEmail = new SendSmtpEmail(); - sendSmtpEmail.subject = "You've reached your limit on Litlyx!"; + sendSmtpEmail.subject = "🚨 You've reached your limit on Litlyx!"; sendSmtpEmail.sender = { "name": "Litlyx", "email": "help@litlyx.com" }; sendSmtpEmail.to = [{ "email": target }]; sendSmtpEmail.htmlContent = LIMIT_MAX_EMAIL @@ -108,17 +108,17 @@ class EmailService { }) { try { const sendSmtpEmail = new SendSmtpEmail(); - sendSmtpEmail.subject = "🚨 Unexpected Activity Detected by our AI"; + sendSmtpEmail.subject = "🔍 Unexpected Activity Detected by our AI"; sendSmtpEmail.sender = { "name": "Litlyx", "email": "help@litlyx.com" }; sendSmtpEmail.to = [{ "email": target }]; sendSmtpEmail.htmlContent = ANOMALY_VISITS_EVENTS_EMAIL .replace(/\[Project Name\]/, projectName) .replace(/\[ENTRIES\]/, [ - ...data.visits.map(e => (`
  • Visits in date ${e._id} [ ${e.count} ]
  • `)), - ...data.events.map(e => (`
  • Events in date ${e._id} [ ${e.count} ]
  • `)) + ...data.visits.map(e => (`
  • Visits in date ${new Date(e._id).toLocaleDateString('en-EN')} [ ${e.count} ]
  • `)), + ...data.events.map(e => (`
  • Events in date ${new Date(e._id).toLocaleDateString('en-EN')} [ ${e.count} ]
  • `)) ] - .join('
    ') + .join('') ) .toString(); await this.apiInstance.sendTransacEmail(sendSmtpEmail); @@ -132,15 +132,15 @@ class EmailService { async sendAnomalyDomainEmail(target: string, projectName: string, domains: string[]) { try { const sendSmtpEmail = new SendSmtpEmail(); - sendSmtpEmail.subject = "🚨 Anomaly detected by our AI"; + sendSmtpEmail.subject = "🔍 Suspicious dns detected by our AI"; sendSmtpEmail.sender = { "name": "Litlyx", "email": "help@litlyx.com" }; sendSmtpEmail.to = [{ "email": target }]; sendSmtpEmail.htmlContent = ANOMALY_DOMAIN_EMAIL .replace(/\[Project Name\]/, projectName) .replace(/\[CURRENT_DATE\]/, new Date().toLocaleDateString('en-EN')) - .replace(/\[DNS_ENTRIES\]/, - domains.map(e => (`
  • ${e}
  • `)).join('
    ') - ) + // .replace(/\[DNS_ENTRIES\]/, + // domains.map(e => (`
  • ${e}
  • `)).join('
    ') + .replace(/\[DNS_ENTRIES\]/, domains[0]) .toString(); await this.apiInstance.sendTransacEmail(sendSmtpEmail); return true; diff --git a/shared/services/email_templates/AnomalyDomainEmail.ts b/shared/services/email_templates/AnomalyDomainEmail.ts index 67b3c6a..102801c 100644 --- a/shared/services/email_templates/AnomalyDomainEmail.ts +++ b/shared/services/email_templates/AnomalyDomainEmail.ts @@ -1,55 +1,159 @@ -export const ANOMALY_DOMAIN_EMAIL = ` - +export const ANOMALY_DOMAIN_EMAIL = ` + + - - - - ❗️ Anomaly detected by our AI + + + + - - + + + + + + + +
    -

    Dear User,

    + + + + + + +
    + + + + + + +
    + + + + + + +
    +

    + Dear user +

    +

    + Our AI Agent noticed a recent Anomaly on your project on Litlyx. +

    +

    + Time: [CURRENT_DATE] + +

    +

    + Project: [Project Name] +

    +

    + Suspicious DNS: [DNS_ENTRIES] +

    +

    + If this was you, there's nothing else you + need to do. +

    -

    We wanted to let you know that [Project Name] on Litlyx has an anomaly that our AI agent detected.

    +
    -

    Anomaly: Suspicious DNS

    + + + + + + +
    + + Go to Dashboard +
    -

    Message:

    + + + + + + +
    +

    If this wasn't you..

    -
      - [DNS_ENTRIES] -
    +

    you should reach out to the webmasters of + the websites that have duplicated your content and request them + to remove it or give you proper attribution (if available).

    -

    Date: [CURRENT_DATE]

    +

    You can also use https://www.whois.com/whois/ + to get the contact details of the webmaster or domain owner.

    -

    Are logging data in your project. Is that you?

    +

    If webmasters don't respond or cooperate, you can file a + DMCA complaint here: https://support.google.com/legal/answer/3110420?hl=en + with Google to request the removal of the duplicate + content from their search results.

    -

    You can analyze a suspicious DNS on your Litlyx dashboard. Visit the Security tab to find out more.

    +

    Please refer to this for more information:

    -

    What can I do?

    + -

    To resolve this issue, you should reach out to the webmasters of the websites that have duplicated your content and request them to remove it or give you proper attribution (if available).

    +

    Your safety is our main priority.

    -

    You can also use https://www.whois.com/whois/ to get the contact details of the webmaster or domain owner.

    +

    Thank you for choosing Litlyx every day as your analytics tool! +

    -

    If webmasters don't respond or cooperate, you can file a DMCA complaint here: https://support.google.com/legal/answer/3110420?hl=en with Google to request the removal of the duplicate content from their search results.

    +

    Antonio,

    +

    CEO | Litlyx

    +
    -

    Please refer to this for more information:

    - - -

    Your safety is our main priority.

    - -

    Thank you for choosing Litlyx every day as your analytics tool!

    - -

    Antonio,

    -

    CEO | Litlyx

    +
    + + + + + + +
    + +
    +

    + 2024 © Litlyx. All rights reserved. +
    + Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA: 17814721001- REA: RM-1743194 +

    +
    + ` \ No newline at end of file diff --git a/shared/services/email_templates/AnomalyUsageEmail.ts b/shared/services/email_templates/AnomalyUsageEmail.ts index b9c786c..d4acffe 100644 --- a/shared/services/email_templates/AnomalyUsageEmail.ts +++ b/shared/services/email_templates/AnomalyUsageEmail.ts @@ -1,50 +1,152 @@ -export const ANOMALY_VISITS_EVENTS_EMAIL = ` - +export const ANOMALY_VISITS_EVENTS_EMAIL = ` + + - - - - 🚨 Unexpected Activity Detected by our AI + + + - - + + + + + + + +
    -

    Dear User,

    + + + + + + +
    + + + + + + +
    + + + + + + +
    +

    + Dear user +

    +

    + Our AI Agent noticed a recent unexpected usage on your project + on Litlyx. +

    +

    + Project: [Project Name] +

    +

    + Info: [ENTRIES] +

    +

    If this spike in activity is expected, there’s no need to worry. + However, if you believe this could be unexpected or suspicious, + we recommend taking a closer look at your data on the + Litlyx Dashboard. You can analyze your recent + traffic and event logs to identify any irregularities or + potential issues.

    -

    We wanted to let you know that [Project Name] on Litlyx is receiving an unexpected amount of visits or events. This could indicate unusual activity that might require your attention.

    -

    Anomaly: Unexpected usage

    +
    -

    Message:

    + + + + + + +
    + + Go to Dashboard +
    -
      - [ENTRIES] -
    + + + + + + +
    + +

    What can I do?

    -

    If this spike in activity is expected, there’s no need to worry. However, if you believe this could be unexpected or suspicious, we recommend taking a closer look at your data on the Litlyx Dashboard. You can analyze your recent traffic and event logs to identify any irregularities or potential issues.

    +

    To better understand the situation, you can:

    -

    What can I do?

    +
      +
    1. Review your traffic sources to see where the visits or + events are coming from.
    2. +
    3. Check for any unexpected patterns, such as a high number of + visits from unknown sources or abnormal event triggers.
    4. +
    5. Check your code to find bugs on a specific action that is + triggered in loops.
    6. +
    -

    To better understand the situation, you can:

    +

    If you need help understanding this activity or have any + concerns, feel free to reach out to our support team at help@litlyx.com. + We are here to assist you!

    -
      -
    1. Review your traffic sources to see where the visits or events are coming from.
    2. -
    3. Check for any unexpected patterns, such as a high number of visits from unknown sources or abnormal event triggers.
    4. -
    5. Check your code to find bugs on a specific action that is triggered in loops.
    6. -
    +

    Your safety and data integrity are our top + priorities.

    -

    If you need help understanding this activity or have any concerns, feel free to reach out to our support team at help@litlyx.com. We are here to assist you!

    +

    Thank you for trusting Litlyx as your analytics tool!

    -

    Your safety and data integrity are our top priorities.

    +

    Best regards,

    -

    Thank you for trusting Litlyx as your analytics tool!

    +

    Antonio,

    +

    CEO | Litlyx

    +
    -

    Best regards,

    -

    Antonio,

    -

    CEO | Litlyx

    +
    + + + + + + +
    + +
    +

    + 2024 © Litlyx. All rights reserved. +
    + Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA: 17814721001- REA: RM-1743194 +

    +
    + ` \ No newline at end of file diff --git a/shared/services/email_templates/Limit50Email.ts b/shared/services/email_templates/Limit50Email.ts index 8b9ca46..496a909 100644 --- a/shared/services/email_templates/Limit50Email.ts +++ b/shared/services/email_templates/Limit50Email.ts @@ -1,31 +1,116 @@ -export const LIMIT_50_EMAIL = ` - +export const LIMIT_50_EMAIL = ` + + - - - - You’ve reached 50% limit on Litlyx + + + + + - -

    Dear User,

    + + + + + + + +
    -

    We wanted to let you know that [Project Name] on Litlyx has reached 50% of its data collection limit for this month.

    + + + + + + +
    + Founder +
    + + + + + + +
    + + + +

    + You’ve Reached 50% of Your Litlyx Project Limit on [Project Name] +

    +

    + To avoid losing precious data, please remember to monitor your usage + on the Litlyx Dashboard. You can find your current + usage details under Settings > Billing Tab +

    -

    To avoid losing precious data, please remember to monitor your usage on the Litlyx Dashboard. You can find your current usage details under Settings > Billing Tab.

    +

    If you need more data collection storage, you may consider upgrading + your plan to get additional benefits and ensure uninterrupted data + collection.

    -

    If you need more data collection storage, you may consider upgrading your plan to get additional benefits and ensure uninterrupted data collection.

    +

    Feel free to reply to this email or contact us at help@litlyx.com + if you have any questions or need assistance.

    -

    Feel free to reply to this email or contact us at help@litlyx.com if you have any questions or need assistance.

    +

    Thank you for choosing Litlyx every day as your analytics tool.

    -

    Thank you for choosing Litlyx every day as your analytics tool.

    +

    Have a nice day!

    -

    Have a nice day!

    +

    Antonio,

    +

    CEO | Litlyx

    -

    Antonio,

    -

    CEO | Litlyx

    + + Go to Dashboard + + +
    +
    +
    + + + + + + +
    + + + +

    + 2024 © Litlyx. All rights reserved. +
    + Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA: + 17814721001- REA: RM-1743194 +

    + + + +
    +
    +
    + - + ` diff --git a/shared/services/email_templates/Limit90Email.ts b/shared/services/email_templates/Limit90Email.ts index 97e9f7a..dc53f84 100644 --- a/shared/services/email_templates/Limit90Email.ts +++ b/shared/services/email_templates/Limit90Email.ts @@ -1,31 +1,117 @@ -export const LIMIT_90_EMAIL = ` - +export const LIMIT_90_EMAIL = ` + + - - - - You’ve reached 90% limit on Litlyx + + + + + - -

    Dear User,

    + + + + + + + +
    -

    We wanted to let you know that [Project Name] on Litlyx has reached 90% of its data collection limit for this month.

    + + + + + + +
    + Founder +
    + + + + + + +
    + + + +

    + You’ve Reached 90% of Your Litlyx Project Limit on [Project Name] +

    +

    + To avoid losing precious data, please remember to monitor your usage + on the Litlyx Dashboard. You can find your current + usage details under Settings > Billing Tab +

    -

    To avoid losing precious data, please remember to monitor your usage on the Litlyx Dashboard. You can find your current usage details under Settings > Billing Tab.

    +

    If you need more data collection storage, you may consider upgrading + your plan to get additional benefits and ensure uninterrupted data + collection.

    -

    If you need more data collection storage, you may consider upgrading your plan to get additional benefits and ensure uninterrupted data collection.

    +

    Feel free to reply to this email or contact us at help@litlyx.com + if you have any questions or need assistance.

    -

    Feel free to reply to this email or contact us at help@litlyx.com if you have any questions or need assistance.

    +

    Thank you for choosing Litlyx every day as your analytics tool.

    -

    Thank you for choosing Litlyx every day as your analytics tool.

    +

    Have a nice day!

    -

    Have a nice day!

    +

    Antonio,

    +

    CEO | Litlyx

    -

    Antonio,

    -

    CEO | Litlyx

    + + Go to Dashboard + + +
    +
    +
    + + + + + + +
    + + + +

    + 2024 © Litlyx. All rights reserved. +
    + Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA: + 17814721001- REA: RM-1743194 +

    + + + +
    +
    +
    + + ` diff --git a/shared/services/email_templates/LimitMaxEmail.ts b/shared/services/email_templates/LimitMaxEmail.ts index ec01294..8d15df3 100644 --- a/shared/services/email_templates/LimitMaxEmail.ts +++ b/shared/services/email_templates/LimitMaxEmail.ts @@ -1,32 +1,138 @@ -export const LIMIT_MAX_EMAIL = ` - +export const LIMIT_MAX_EMAIL = ` + + - - - - ❗️ You’ve reached your limit on Litlyx! + + + + + - -

    Dear User,

    + + + + + + + +
    -

    We wanted to let you know that [Project Name] on Litlyx has reached the limit of your current plan.

    + + + + + + +
    + Founder +
    + + + + + + +
    + + + +

    + You’ve Reached Your Litlyx Project Limit on [Project Name] +

    +

    + We noticed that Litlyx has stopped collecting data for your project. +

    -

    To avoid losing precious data, please remember to monitor your usage on the Litlyx Dashboard. You can find your current usage details under Settings > Billing Tab.

    +

    + To help you avoid losing valuable insights, we recommend keeping an + eye on your usage via the Litlyx Dashboard. +

    -

    If you need more data collection storage, you may consider upgrading your plan to get additional benefits and ensure uninterrupted data collection.

    +

    + You can view your current usage details under Settings > Billing + Tab. +

    -

    Feel free to reply to this email or contact us at help@litlyx.com if you have any questions or need assistance.

    +

    + If you need additional storage for data collection, consider + upgrading your plan to unlock more benefits and ensure uninterrupted + service. +

    +

    + As a token of appreciation, we're offering you 25% off for life at + checkout with the code LIT25. +

    + Thank you for choosing Litlyx as your trusted analytics tool. +

    -

    Thank you for choosing Litlyx every day as your analytics tool.

    +

    + If you have any questions or need assistance, feel free to reply to + this email or contact us at help@litlyx.com +

    -

    Have a nice day!

    +

    + Have a great day! +

    -

    Antonio,

    -

    CEO | Litlyx

    +

    + Antonio + CEO | Litlyx +

    + + + + Go + to Dashboard + + +
    +
    +
    + + + + + + +
    + + + +

    + 2024 © Litlyx. All rights reserved. +
    + Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA: + 17814721001- REA: RM-1743194 +

    + + + +
    +
    +
    + + - `