From 73739dde9de76b74b5110ebccab949401d1c9ca1 Mon Sep 17 00:00:00 2001 From: Emily Date: Sat, 7 Sep 2024 15:47:13 +0200 Subject: [PATCH] fix pricing + limits email + redis --- broker/src/Controller.ts | 68 +++- .../components/pricing/PricingDrawer.vue | 4 +- dashboard/server/api/project/generate_pdf.ts | 6 +- landing/pages/pricing.vue | 4 +- shared/data/broker/Limits.ts | 4 +- shared/services/EmailService.ts | 49 ++- shared/services/RedisStreamService.ts | 10 +- .../services/email_templates/Limit50Email.ts | 114 +----- .../services/email_templates/Limit90Email.ts | 31 ++ .../services/email_templates/LimitMaxEmail.ts | 32 ++ .../services/email_templates/WelcomeEmail.ts | 385 ++---------------- shared/services/email_templates/limit_50.html | 32 ++ shared/services/email_templates/limit_90.html | 32 ++ .../services/email_templates/limit_max.html | 32 ++ shared/services/email_templates/welcome.html | 40 ++ 15 files changed, 361 insertions(+), 482 deletions(-) create mode 100644 shared/services/email_templates/Limit90Email.ts create mode 100644 shared/services/email_templates/LimitMaxEmail.ts create mode 100644 shared/services/email_templates/limit_50.html create mode 100644 shared/services/email_templates/limit_90.html create mode 100644 shared/services/email_templates/limit_max.html create mode 100644 shared/services/email_templates/welcome.html diff --git a/broker/src/Controller.ts b/broker/src/Controller.ts index 57c17c6..6c6dac6 100644 --- a/broker/src/Controller.ts +++ b/broker/src/Controller.ts @@ -11,15 +11,63 @@ if (process.env.EMAIL_SERVICE) { export async function checkLimitsForEmail(projectCounts: TProjectLimit) { - if ((projectCounts.visits + projectCounts.events) >= (projectCounts.limit / 2)) { - const notify = await LimitNotifyModel.findOne({ project_id: projectCounts._id }); - if (notify && notify.limit1 === true) return; - const project = await ProjectModel.findById(projectCounts.project_id); - if (!project) return; - const owner = await UserModel.findById(project.owner); - if (!owner) return; - if (process.env.EMAIL_SERVICE) await EmailService.sendLimitEmail50(owner.email); - await LimitNotifyModel.updateOne({ project_id: projectCounts._id }, { limit1: true, limit2: false, limit3: false }, { upsert: true }); + console.log('CHECK LIMIT EMAIL'); + + const project_id = projectCounts.project_id; + const hasNotifyEntry = await LimitNotifyModel.findOne({ project_id }); + if (!hasNotifyEntry) { + await LimitNotifyModel.create({ project_id, limit1: false, limit2: false, limit3: false }) } -} \ No newline at end of file + if ((projectCounts.visits + projectCounts.events) >= (projectCounts.limit)) { + console.log('LIMIT 3'); + + const notify = await LimitNotifyModel.findOne({ project_id }); + if (notify && notify.limit3 === true) return; + + const project = await ProjectModel.findById(project_id); + if (!project) return; + + const owner = await UserModel.findById(project.owner); + if (!owner) return; + + if (process.env.EMAIL_SERVICE) await EmailService.sendLimitEmailMax(owner.email, project.name); + await LimitNotifyModel.updateOne({ project_id: projectCounts.project_id }, { limit1: true, limit2: true, limit3: true }); + + } else if ((projectCounts.visits + projectCounts.events) >= (projectCounts.limit * 0.9)) { + console.log('LIMIT 2'); + + const notify = await LimitNotifyModel.findOne({ project_id }); + if (notify && notify.limit2 === true) return; + + const project = await ProjectModel.findById(project_id); + if (!project) return; + + const owner = await UserModel.findById(project.owner); + if (!owner) return; + + if (process.env.EMAIL_SERVICE) await EmailService.sendLimitEmail90(owner.email, project.name); + await LimitNotifyModel.updateOne({ project_id: projectCounts.project_id }, { limit1: true, limit2: true, limit3: false }); + + } else if ((projectCounts.visits + projectCounts.events) >= (projectCounts.limit * 0.5)) { + + console.log('LIMIT 1'); + + const notify = await LimitNotifyModel.findOne({ project_id }); + if (notify && notify.limit1 === true) return; + + const project = await ProjectModel.findById(project_id); + if (!project) return; + + const owner = await UserModel.findById(project.owner); + if (!owner) return; + + if (process.env.EMAIL_SERVICE) await EmailService.sendLimitEmail50(owner.email, project.name); + await LimitNotifyModel.updateOne({ project_id: projectCounts.project_id }, { limit1: true, limit2: false, limit3: false }); + + } + + + + +} diff --git a/dashboard/components/pricing/PricingDrawer.vue b/dashboard/components/pricing/PricingDrawer.vue index a8c0791..ce5e3b6 100644 --- a/dashboard/components/pricing/PricingDrawer.vue +++ b/dashboard/components/pricing/PricingDrawer.vue @@ -213,7 +213,7 @@ async function onLifetimeUpgradeClick() { LIFETIME DEAL - (Growh plan) + (Growth plan)
€ 2.399,00
Up to 500.000 visits/events per month
@@ -245,7 +245,7 @@ async function onLifetimeUpgradeClick() {
Check -
Data retention: 1 Year
+
Data retention: 5 Years
diff --git a/dashboard/server/api/project/generate_pdf.ts b/dashboard/server/api/project/generate_pdf.ts index dd1468a..8152ee9 100644 --- a/dashboard/server/api/project/generate_pdf.ts +++ b/dashboard/server/api/project/generate_pdf.ts @@ -129,9 +129,9 @@ export default defineEventHandler(async event => { const firstEventDate = await EventModel.findOne({ project_id: project._id }, { created_at: 1 }, { sort: { created_at: 1 } }); const firstViewDate = await VisitModel.findOne({ project_id: project._id }, { created_at: 1 }, { sort: { created_at: 1 } }); - if (!firstEventDate || !firstViewDate) { - return setResponseStatus(event, 400, 'Not enough data to generate report'); - } + // if (!firstEventDate || !firstViewDate) { + // return setResponseStatus(event, 400, 'Not enough data to generate report'); + // } const avgEventsDay = () => { const days = (Date.now() - (firstEventDate?.created_at.getTime() || 0)) / 1000 / 60 / 60 / 24; diff --git a/landing/pages/pricing.vue b/landing/pages/pricing.vue index 8b9c97b..7a83628 100644 --- a/landing/pages/pricing.vue +++ b/landing/pages/pricing.vue @@ -189,7 +189,7 @@ const slidePricings: PricingCardProp[] = [ LIFETIME DEAL - (Growh plan) + (Growth plan)
€ 2.399,00
Up to 500.000 visits/events per month
@@ -221,7 +221,7 @@ const slidePricings: PricingCardProp[] = [
Check -
Data retention: 1 Year
+
Data retention: 5 Years
diff --git a/shared/data/broker/Limits.ts b/shared/data/broker/Limits.ts index 4a8c0ef..c2e2fb9 100644 --- a/shared/data/broker/Limits.ts +++ b/shared/data/broker/Limits.ts @@ -1,5 +1,5 @@ -// Default: 1.1 +// Default: 1.01 // ((events + visits) * VALUE) > limit -export const EVENT_LOG_LIMIT_PERCENT = 1.1; \ No newline at end of file +export const EVENT_LOG_LIMIT_PERCENT = 1.01; \ No newline at end of file diff --git a/shared/services/EmailService.ts b/shared/services/EmailService.ts index 05b9263..c4e92ae 100644 --- a/shared/services/EmailService.ts +++ b/shared/services/EmailService.ts @@ -1,6 +1,8 @@ import { TransactionalEmailsApi, SendSmtpEmail } from '@getbrevo/brevo'; import { WELCOME_EMAIL } from './email_templates/WelcomeEmail'; import { LIMIT_50_EMAIL } from './email_templates/Limit50Email'; +import { LIMIT_90_EMAIL } from './email_templates/Limit90Email'; +import { LIMIT_MAX_EMAIL } from './email_templates/LimitMaxEmail'; class EmailService { @@ -11,13 +13,51 @@ class EmailService { this.apiInstance.setApiKey(0, apiKey); } - async sendLimitEmail50(target: string) { + async sendLimitEmail50(target: string, projectName: string) { try { const sendSmtpEmail = new SendSmtpEmail(); - sendSmtpEmail.subject = "Litlyx project limit 50%"; + sendSmtpEmail.subject = "You've reached 50% limit on Litlyx"; sendSmtpEmail.sender = { "name": "Litlyx", "email": "no-reply@litlyx.com" }; sendSmtpEmail.to = [{ "email": target }]; - sendSmtpEmail.htmlContent = LIMIT_50_EMAIL; + + sendSmtpEmail.htmlContent = LIMIT_50_EMAIL + .replace(/\[Project Name\]/, projectName) + .toString(); + + await this.apiInstance.sendTransacEmail(sendSmtpEmail); + return true; + } catch (ex) { + console.error('ERROR SENDING EMAIL', ex); + return false; + } + } + + async sendLimitEmail90(target: string, projectName: string) { + try { + const sendSmtpEmail = new SendSmtpEmail(); + sendSmtpEmail.subject = "You've reached 90% limit on Litlyx"; + sendSmtpEmail.sender = { "name": "Litlyx", "email": "no-reply@litlyx.com" }; + sendSmtpEmail.to = [{ "email": target }]; + sendSmtpEmail.htmlContent = LIMIT_90_EMAIL + .replace(/\[Project Name\]/, projectName) + .toString(); + await this.apiInstance.sendTransacEmail(sendSmtpEmail); + return true; + } catch (ex) { + console.error('ERROR SENDING EMAIL', ex); + return false; + } + } + + async sendLimitEmailMax(target: string, projectName: string) { + try { + const sendSmtpEmail = new SendSmtpEmail(); + sendSmtpEmail.subject = "You've reached your limit on Litlyx!"; + sendSmtpEmail.sender = { "name": "Litlyx", "email": "no-reply@litlyx.com" }; + sendSmtpEmail.to = [{ "email": target }]; + sendSmtpEmail.htmlContent = LIMIT_MAX_EMAIL + .replace(/\[Project Name\]/, projectName) + .toString(); await this.apiInstance.sendTransacEmail(sendSmtpEmail); return true; } catch (ex) { @@ -28,9 +68,8 @@ class EmailService { async sendWelcomeEmail(target: string) { try { - console.log('SENDING WELCOME EMAIL_EMAIL SERVICE') const sendSmtpEmail = new SendSmtpEmail(); - sendSmtpEmail.subject = "Welcome to Litlyx"; + sendSmtpEmail.subject = "Welcome to Litlyx!"; sendSmtpEmail.sender = { "name": "Litlyx", "email": "no-reply@litlyx.com" }; sendSmtpEmail.to = [{ "email": target }]; sendSmtpEmail.htmlContent = WELCOME_EMAIL; diff --git a/shared/services/RedisStreamService.ts b/shared/services/RedisStreamService.ts index ed76c0e..c0b49c3 100644 --- a/shared/services/RedisStreamService.ts +++ b/shared/services/RedisStreamService.ts @@ -25,10 +25,7 @@ export class RedisStreamService { static async connect() { console.log('RedisStreamService DEV_MODE=', process.env.DEV_MODE === 'true'); await this.client.connect(); - setInterval(() => { - console.log('Processed:', (RedisStreamService.processed / 30).toFixed(), '/s'); - RedisStreamService.processed = 0; - }, 30_000) + } @@ -48,6 +45,11 @@ export class RedisStreamService { static async startReadingLoop(options: ReadingLoopOptions, processFunction: (content: Record) => Promise) { + setInterval(() => { + console.log('Processed:', (RedisStreamService.processed / 30).toFixed(), '/s'); + RedisStreamService.processed = 0; + }, 30_000) + try { console.log('Start reading loop'); await this.client.xGroupCreate(options.streamName, 'broker', '0', { MKSTREAM: true, }); diff --git a/shared/services/email_templates/Limit50Email.ts b/shared/services/email_templates/Limit50Email.ts index e23b8b9..8b9ca46 100644 --- a/shared/services/email_templates/Limit50Email.ts +++ b/shared/services/email_templates/Limit50Email.ts @@ -1,101 +1,31 @@ -export const LIMIT_50_EMAIL = ` - +export const LIMIT_50_EMAIL = ` - + - LitLyx Limit Reached 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.

+ +

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.

+ +

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.

+ +

Have a nice day!

+ +

Antonio,

+

CEO | Litlyx

- -
-
-

⚠ Limit for project ⚠

-
-
-

Hey there! We found that one of your projects is at 50% of the limit of the plan. In order to continue to log visits & events, you should upgrade the plan of your project!

-
-
-

How can I upgrade the plan?

-

We offer different plans, each of them follows the stage of your project, so based on the reach, you should upgrade to the most appropriate one for your web platform. It takes 1 minute to upgrade the plan! You can find everything in the "Billing" section in the left menu of your dashboard.

- Visit your dashboard -
-
-

We are in early phases!

-

Want to become an early adopter? Book a demo with me! I'm Antonio & I'll guide you through all the features and benefits of LitLyx. A big discount is waiting for you❗️❗️❗️

- Book a Demo with Me! -
- -
- + ` diff --git a/shared/services/email_templates/Limit90Email.ts b/shared/services/email_templates/Limit90Email.ts new file mode 100644 index 0000000..97e9f7a --- /dev/null +++ b/shared/services/email_templates/Limit90Email.ts @@ -0,0 +1,31 @@ +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.

+ +

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.

+ +

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.

+ +

Have a nice day!

+ +

Antonio,

+

CEO | Litlyx

+ + + + +` diff --git a/shared/services/email_templates/LimitMaxEmail.ts b/shared/services/email_templates/LimitMaxEmail.ts new file mode 100644 index 0000000..ec01294 --- /dev/null +++ b/shared/services/email_templates/LimitMaxEmail.ts @@ -0,0 +1,32 @@ +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.

+ +

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.

+ +

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.

+ +

Have a nice day!

+ +

Antonio,

+

CEO | Litlyx

+ + + + + +` diff --git a/shared/services/email_templates/WelcomeEmail.ts b/shared/services/email_templates/WelcomeEmail.ts index fc100c8..3e9da62 100644 --- a/shared/services/email_templates/WelcomeEmail.ts +++ b/shared/services/email_templates/WelcomeEmail.ts @@ -1,378 +1,39 @@ export const WELCOME_EMAIL = ` - + - + + + - - Welcome Email Litlyx - - - - - - - - - - - + ` \ No newline at end of file diff --git a/shared/services/email_templates/limit_50.html b/shared/services/email_templates/limit_50.html new file mode 100644 index 0000000..b068122 --- /dev/null +++ b/shared/services/email_templates/limit_50.html @@ -0,0 +1,32 @@ + + + + + + + You’ve reached 50% limit on Litlyx + + + + +

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.

+ +

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.

+ +

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.

+ +

Have a nice day!

+ +

Antonio,

+

CEO | Litlyx

+ + + diff --git a/shared/services/email_templates/limit_90.html b/shared/services/email_templates/limit_90.html new file mode 100644 index 0000000..49fc892 --- /dev/null +++ b/shared/services/email_templates/limit_90.html @@ -0,0 +1,32 @@ + + + + + + + You’ve reached 90% limit on Litlyx + + + + +

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.

+ +

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.

+ +

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.

+ +

Have a nice day!

+ +

Antonio,

+

CEO | Litlyx

+ + + diff --git a/shared/services/email_templates/limit_max.html b/shared/services/email_templates/limit_max.html new file mode 100644 index 0000000..ea69d2c --- /dev/null +++ b/shared/services/email_templates/limit_max.html @@ -0,0 +1,32 @@ + + + + + + + ❗️ You’ve reached your limit on Litlyx! + + + + +

❗️ 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.

+ +

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.

+ +

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.

+ +

Have a nice day!

+ +

Antonio,

+

CEO | Litlyx

+ + + diff --git a/shared/services/email_templates/welcome.html b/shared/services/email_templates/welcome.html new file mode 100644 index 0000000..0b2764d --- /dev/null +++ b/shared/services/email_templates/welcome.html @@ -0,0 +1,40 @@ + + + + + + + Welcome to Litlyx! + + + + +

Welcome to Litlyx!

+ +

We’re happy to have you onboard,

+ +

At Litlyx, we’re committed to creating the best analytics collection experience for everybody, starting from developers.

+ +

Here are a few things you can do to get started tracking analytics today:

+ +
    +
  1. Create a new project – by just naming it
  2. +
  3. Copy the universal Script – we provide you the snippets to copy in your index.html file and start instantly to track metrics on your website or web app.
  4. +
  5. Third Step – Encourage engagement or interaction.
  6. +
+ +

If you have any questions or need support, visit docs.litlyx.com.

+ +

Feel free to reply to this email or reach out to our team at help@litlyx.com. We’re here to help!

+ +

Link to Discord for developer support: https://discord.com/invite/9cQykjsmWX

+ +

Thank you for joining us, and we look forward to seeing you around.

+ +

We want to make analytics the freshest thing on the web.

+ +

Antonio,

+

CEO | Litlyx

+ + + \ No newline at end of file