mirror of
https://github.com/Litlyx/litlyx
synced 2026-02-04 06:32:20 +01:00
new selfhosted version
This commit is contained in:
3
emails/.gitignore
vendored
Normal file
3
emails/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
src/shared
|
||||
dist
|
||||
12
emails/ecosystem.config.js
Normal file
12
emails/ecosystem.config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: 'email-service',
|
||||
port: '3020',
|
||||
exec_mode: 'cluster',
|
||||
instances: '1',
|
||||
script: './dist/src/index.js',
|
||||
env: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
29
emails/package.json
Normal file
29
emails/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "emails",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"dev:prod": "ts-node ../scripts/emails/run_local.ts --production",
|
||||
"dev:test": "ts-node ../scripts/emails/run_local.ts --testmode",
|
||||
"shared": "ts-node ../scripts/emails/shared.ts",
|
||||
"deploy": "ts-node ../scripts/emails/deploy.ts",
|
||||
"build": "tsc"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "Emily",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@getbrevo/brevo": "^2.2.0",
|
||||
"@trpc/server": "11.2.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^5.1.0",
|
||||
"mongoose": "^8.15.0",
|
||||
"zod": "3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cors": "^2.8.18",
|
||||
"@types/express": "^5.0.2",
|
||||
"@types/node": "^22.15.19"
|
||||
}
|
||||
}
|
||||
1905
emails/pnpm-lock.yaml
generated
Normal file
1905
emails/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
emails/src/index.ts
Normal file
42
emails/src/index.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { router, createContext } from './trpc';
|
||||
import express from 'express';
|
||||
import cors from 'cors';
|
||||
|
||||
const app = express();
|
||||
app.use(cors());
|
||||
|
||||
import * as trpcExpress from '@trpc/server/adapters/express';
|
||||
import { emailRouter } from './routers/EmailRouter'
|
||||
import { brevoRouter } from './routers/BrevoRouter'
|
||||
import { EmailService } from './services/EmailService'
|
||||
|
||||
if (!process.env.PORT) throw Error('PORT is required');
|
||||
|
||||
if (process.env.BREVO_KEY) {
|
||||
EmailService.init(process.env.BREVO_KEY);
|
||||
} else {
|
||||
throw Error('BREVO_KEY is required');
|
||||
}
|
||||
|
||||
export type AppRouter = typeof appRouter;
|
||||
|
||||
const appRouter = router({
|
||||
email: emailRouter,
|
||||
brevo: brevoRouter
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.use('/trpc', trpcExpress.createExpressMiddleware({ router: appRouter, createContext }));
|
||||
|
||||
const port = parseInt(process.env.PORT);
|
||||
if (!port) {
|
||||
console.error('PORT is not set');
|
||||
process.exit();
|
||||
}
|
||||
if (isNaN(port)) {
|
||||
console.error('PORT is not a valid number');
|
||||
process.exit();
|
||||
}
|
||||
|
||||
app.listen(port, () => console.log(`[EMAILS] Listening on port ${port}`));
|
||||
12
emails/src/routers/BrevoRouter.ts
Normal file
12
emails/src/routers/BrevoRouter.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { protectedProcedure, router } from '../trpc';
|
||||
import { EmailService } from '../services/EmailService';
|
||||
import z from 'zod';
|
||||
|
||||
const ZAddToBrevoListInput = z.object({ email: z.string().email() });
|
||||
|
||||
export const brevoRouter = router({
|
||||
addToBrevoList: protectedProcedure.input(ZAddToBrevoListInput).mutation(async (opts) => {
|
||||
const result = await EmailService.createContact(opts.input.email);
|
||||
return { ok: result };
|
||||
}),
|
||||
});
|
||||
194
emails/src/routers/EmailRouter.ts
Normal file
194
emails/src/routers/EmailRouter.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
import { protectedProcedure, router } from '../trpc';
|
||||
import { EmailService } from '../services/EmailService';
|
||||
import z from 'zod';
|
||||
|
||||
const ZWelcomeInput = z.object({ email: z.string().email() });
|
||||
const ZConfirmInput = z.object({ email: z.string().email(), link: z.string() });
|
||||
const ZInviteInput = z.object({ email: z.string().email(), project_name: z.string(), link: z.string() });
|
||||
const ZLimitInput = z.object({ email: z.string().email() });
|
||||
const ZResetPasswordInput = z.object({ email: z.string().email(), link: z.string() });
|
||||
|
||||
|
||||
const ZEmailWithoutParamsInput = z.object({ email: z.string().email() });
|
||||
|
||||
const ZSelfhostedInput = z.object({ email: z.string().email(), code: z.string() });
|
||||
|
||||
const ZTrialEndsTomorrowInput = z.object({
|
||||
email: z.string().email(),
|
||||
visits: z.number(),
|
||||
plan: z.string()
|
||||
});
|
||||
|
||||
const ZTrialEndsTodayInput = z.object({
|
||||
email: z.string().email(),
|
||||
visits: z.number(),
|
||||
plan: z.string()
|
||||
});
|
||||
|
||||
export const emailRouter = router({
|
||||
sendConfirmEmail: protectedProcedure.input(ZConfirmInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: 'Confirm your email',
|
||||
template: 'CONFIRM_EMAIL',
|
||||
params: {
|
||||
'CONFIRM_LINK': opts.input.link
|
||||
}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
sendInviteEmail: protectedProcedure.input(ZInviteInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: '⚡ Invite',
|
||||
template: 'PROJECT_INVITE_EMAIL',
|
||||
params: {
|
||||
'Workspace_Name': opts.input.project_name,
|
||||
'LINK': opts.input.link,
|
||||
}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
sendLimitEmail50: protectedProcedure.input(ZLimitInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "⚡ You've reached 50% limit on Litlyx",
|
||||
template: 'LIMIT_50_EMAIL',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
sendLimitEmail90: protectedProcedure.input(ZLimitInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "⚡ You've reached 90% limit on Litlyx",
|
||||
template: 'LIMIT_90_EMAIL',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
sendLimitEmailMax: protectedProcedure.input(ZLimitInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "🚨 You've reached your limit on Litlyx!",
|
||||
template: 'LIMIT_MAX_EMAIL',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
sendResetPasswordEmail: protectedProcedure.input(ZResetPasswordInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Password reset",
|
||||
template: 'FORGOT_PASSWORD_EMAIL',
|
||||
params: {
|
||||
'LINK': opts.input.link
|
||||
}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
|
||||
send_trial_1_started: protectedProcedure.input(ZEmailWithoutParamsInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Your Litlyx dashboard is live",
|
||||
template: 'N1_FREE_TRIAL_STARTED',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
send_trial_2_10_days_in: protectedProcedure.input(ZEmailWithoutParamsInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Litlyx is tracking your stats",
|
||||
template: 'N2_FREE_TRIAL_10_DAYS_IN',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
send_trial_3_1_week_left: protectedProcedure.input(ZEmailWithoutParamsInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Your Litlyx trial ends in 1 week",
|
||||
template: 'N3_FREE_TRIAL_1_WEEK_LEFT',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
send_trial_4_ends_tomorrow: protectedProcedure.input(ZTrialEndsTomorrowInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Your Litlyx free trial ends tomorrow",
|
||||
template: 'N4_FREE_TRIAL_ENDS_TOMORROW',
|
||||
params: {
|
||||
'NUMBER_OF_VISITS': opts.input.visits.toString(),
|
||||
'PLANS_RECOMMENDED': opts.input.plan
|
||||
}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
send_trial_5_ends_today: protectedProcedure.input(ZTrialEndsTodayInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Your Litlyx free trial ends today",
|
||||
template: 'N5_FREE_TRIAL_ENDS_TODAY',
|
||||
params: {
|
||||
'NUMBER_OF NUMBER_OF_VISITS': opts.input.visits.toString(),
|
||||
'PLANS_RECOMMENDED': opts.input.plan
|
||||
}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
send_trial_6_ended: protectedProcedure.input(ZEmailWithoutParamsInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Your Litlyx free trial has ended",
|
||||
template: 'N6_FREE_TRIAL_HAS_ENDED',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
|
||||
send_trial_7_stop_collecting: protectedProcedure.input(ZEmailWithoutParamsInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Litlyx Tracking stops in 2 days",
|
||||
template: 'N7_LITLYX_WILL_STOP_COLLECTING',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
|
||||
send_trial_8_stop_grace_period: protectedProcedure.input(ZEmailWithoutParamsInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Litlyx Tracking has stopped",
|
||||
template: 'N8_LITLYX_HAS_STOP_GRACE_PERIOD',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
|
||||
sendPurchaseEmail: protectedProcedure.input(ZEmailWithoutParamsInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Your Litlyx plan has been upgraded",
|
||||
template: 'PURCHASE_EMAIL',
|
||||
params: {}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
|
||||
sendPurchaseSelfhostedEmail: protectedProcedure.input(ZSelfhostedInput).mutation(async (opts) => {
|
||||
const result = await EmailService.sendGenericEmail({
|
||||
target: opts.input.email,
|
||||
subject: "Your Litlyx Pro License Key",
|
||||
template: 'PURCHASE_SELFHOST_EMAIL',
|
||||
params: {
|
||||
'LICENSE_KEY_CODE': opts.input.code
|
||||
}
|
||||
});
|
||||
return { ok: result };
|
||||
}),
|
||||
|
||||
});
|
||||
63
emails/src/services/EmailService.ts
Normal file
63
emails/src/services/EmailService.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { TransactionalEmailsApi, SendSmtpEmail, ContactsApi } from '@getbrevo/brevo';
|
||||
import { EMAIL_TEMPLATE_NAME, EMAIL_TEMPLATES, EMAIL_TEMPLATES as TEMPLATE } from './TemplateService'
|
||||
|
||||
|
||||
|
||||
export type SendEmailOptions<Keys extends string[] = any> = {
|
||||
target: string,
|
||||
subject: string,
|
||||
params: Record<Keys[number], string>,
|
||||
template: EMAIL_TEMPLATE_NAME
|
||||
}
|
||||
|
||||
export class EmailService {
|
||||
|
||||
private static apiInstance = new TransactionalEmailsApi();
|
||||
private static apiContacts = new ContactsApi();
|
||||
|
||||
static init(apiKey: string) {
|
||||
this.apiInstance.setApiKey(0, apiKey);
|
||||
this.apiContacts.setApiKey(0, apiKey);
|
||||
}
|
||||
|
||||
|
||||
static async sendGenericEmail<Keys extends string[]>(options: SendEmailOptions<Keys>) {
|
||||
try {
|
||||
const sendSmtpEmail = new SendSmtpEmail();
|
||||
sendSmtpEmail.subject = options.subject;
|
||||
sendSmtpEmail.sender = { "name": "Litlyx", "email": "help@litlyx.com" };
|
||||
sendSmtpEmail.to = [{ "email": options.target }];
|
||||
const templateContent = EMAIL_TEMPLATES[options.template];
|
||||
let templateResult = templateContent;
|
||||
|
||||
const paramKeys = Object.keys(options.params);
|
||||
|
||||
for (const paramKey of paramKeys) {
|
||||
const regexp = new RegExp(`\\[${paramKey}\\]`);
|
||||
templateResult = templateResult.replace(regexp, options.params[paramKey]);
|
||||
}
|
||||
|
||||
templateResult = templateResult.toString();
|
||||
sendSmtpEmail.htmlContent = templateResult;
|
||||
|
||||
|
||||
await this.apiInstance.sendTransacEmail(sendSmtpEmail);
|
||||
return true;
|
||||
} catch (ex) {
|
||||
console.error('ERROR SENDING EMAIL', ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static async createContact(email: string) {
|
||||
try {
|
||||
await this.apiContacts.createContact({ email });
|
||||
await this.apiContacts.addContactToList(12, { emails: [email] })
|
||||
return true;
|
||||
} catch (ex) {
|
||||
console.error('ERROR ADDING CONTACT', ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
47
emails/src/services/TemplateService.ts
Normal file
47
emails/src/services/TemplateService.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { LIMIT_50_EMAIL } from '../../templates/Limit50Email';
|
||||
import { LIMIT_90_EMAIL } from '../../templates/Limit90Email';
|
||||
import { LIMIT_MAX_EMAIL } from '../../templates/LimitMaxEmail';
|
||||
import { PURCHASE_EMAIL } from '../../templates/PurchaseEmail';
|
||||
import { ANOMALY_VISITS_EVENTS_EMAIL } from '../../templates/AnomalyUsageEmail';
|
||||
import { ANOMALY_DOMAIN_EMAIL } from '../../templates/AnomalyDomainEmail';
|
||||
import { CONFIRM_EMAIL } from '../../templates/ConfirmEmail';
|
||||
import { FORGOT_PASSWORD_EMAIL } from '../../templates/ForgotPasswordEmail';
|
||||
import { PROJECT_INVITE_EMAIL } from '../../templates/ProjectInviteEmail';
|
||||
import { PROJECT_INVITE_EMAIL_NO_ACCOUNT } from '../../templates/ProjectInviteEmailNoAccount';
|
||||
import { PURCHASE_SELFHOST_EMAIL } from '../../templates/PurchaseSelfhostEmail';
|
||||
|
||||
import { N1_FREE_TRIAL_STARTED } from '../../templates/free_trial/1-FreeTrialStarted';
|
||||
import { N2_FREE_TRIAL_10_DAYS_IN } from '../../templates/free_trial/2-FreeTrial10DaysIn';
|
||||
import { N3_FREE_TRIAL_1_WEEK_LEFT } from '../../templates/free_trial/3-FreeTrial1WeekLeft';
|
||||
import { N4_FREE_TRIAL_ENDS_TOMORROW } from '../../templates/free_trial/4-FreeTrialEndsTomorrow';
|
||||
import { N5_FREE_TRIAL_ENDS_TODAY } from '../../templates/free_trial/5-FreeTrialEndsToday';
|
||||
import { N6_FREE_TRIAL_HAS_ENDED } from '../../templates/free_trial/6-FreeTrialHasEnded';
|
||||
import { N7_LITLYX_WILL_STOP_COLLECTING } from '../../templates/free_trial/7-LitlyxWillStopCollecting';
|
||||
import { N8_LITLYX_HAS_STOP_GRACE_PERIOD } from '../../templates/free_trial/8-LitlyxHasStopGracePeriod';
|
||||
|
||||
|
||||
export const EMAIL_TEMPLATES = {
|
||||
LIMIT_50_EMAIL,
|
||||
LIMIT_90_EMAIL,
|
||||
LIMIT_MAX_EMAIL,
|
||||
PURCHASE_EMAIL,
|
||||
ANOMALY_VISITS_EVENTS_EMAIL,
|
||||
ANOMALY_DOMAIN_EMAIL,
|
||||
CONFIRM_EMAIL,
|
||||
FORGOT_PASSWORD_EMAIL,
|
||||
PROJECT_INVITE_EMAIL,
|
||||
PROJECT_INVITE_EMAIL_NO_ACCOUNT,
|
||||
|
||||
N1_FREE_TRIAL_STARTED,
|
||||
N2_FREE_TRIAL_10_DAYS_IN,
|
||||
N3_FREE_TRIAL_1_WEEK_LEFT,
|
||||
N4_FREE_TRIAL_ENDS_TOMORROW,
|
||||
N5_FREE_TRIAL_ENDS_TODAY,
|
||||
N6_FREE_TRIAL_HAS_ENDED,
|
||||
N7_LITLYX_WILL_STOP_COLLECTING,
|
||||
N8_LITLYX_HAS_STOP_GRACE_PERIOD,
|
||||
|
||||
PURCHASE_SELFHOST_EMAIL
|
||||
}
|
||||
|
||||
export type EMAIL_TEMPLATE_NAME = keyof typeof EMAIL_TEMPLATES;
|
||||
28
emails/src/trpc.ts
Normal file
28
emails/src/trpc.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { initTRPC, TRPCError } from '@trpc/server';
|
||||
import { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
|
||||
|
||||
const t = initTRPC.context<Context>().create()
|
||||
|
||||
export const router = t.router;
|
||||
const publicProcedure = t.procedure;
|
||||
|
||||
export type Context = ReturnType<typeof createContext>;
|
||||
|
||||
export function createContext({ req }: CreateHTTPContextOptions) {
|
||||
return { headers: req.headers }
|
||||
}
|
||||
|
||||
export const protectedProcedure = publicProcedure.use(async ({ ctx, next }) => {
|
||||
try {
|
||||
const headers = ctx.headers;
|
||||
const authorization = headers.authorization;
|
||||
if (!authorization) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Missing Authorization header' });
|
||||
const [mode, content] = authorization.split(' ');
|
||||
if (mode !== 'Bearer') throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Authorization type not valid' });
|
||||
if (content !== process.env.EMAIL_SECRET) throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Authorization token invalid', });
|
||||
return next();
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
throw new TRPCError({ code: 'UNAUTHORIZED', message: 'Error during authorization' });
|
||||
}
|
||||
});
|
||||
6
emails/src/utils.ts
Normal file
6
emails/src/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { Response } from "express";
|
||||
|
||||
|
||||
export function sendJson(res: Response, status: number, data: Record<string, any>): void {
|
||||
res.status(status).json(data);
|
||||
}
|
||||
159
emails/templates/AnomalyDomainEmail.ts
Normal file
159
emails/templates/AnomalyDomainEmail.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
export const ANOMALY_DOMAIN_EMAIL = `<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html dir="ltr" lang="en">
|
||||
|
||||
<head>
|
||||
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
<!--$-->
|
||||
</head>
|
||||
|
||||
<body
|
||||
style='background-color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif'>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="max-width:37.5em">
|
||||
<tbody>
|
||||
<tr style="width:100%">
|
||||
<td>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="border:1px solid rgb(0,0,0, 0.1);border-radius:3px;overflow:hidden">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<img src="https://litlyx.com/images/locker2.png"
|
||||
style="display:block;outline:none;border:none;text-decoration:none;max-width:100%"
|
||||
width="620" />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation" style="padding:20px;padding-bottom:0">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<td data-id="__react-email-column">
|
||||
<h1 style="font-size:32px;font-weight:bold;text-align:center">
|
||||
Dear user
|
||||
</h1>
|
||||
<h2 style="font-size:26px;font-weight:bold;text-align:center">
|
||||
Our AI Agent noticed a recent Anomaly on your project on Litlyx.
|
||||
</h2>
|
||||
<p style="font-size:16px;line-height:24px;margin:16px 0">
|
||||
<b>Time: </b> [CURRENT_DATE]
|
||||
<!-- September 7, 2022 at 10:58 AM -->
|
||||
</p>
|
||||
<p
|
||||
style="font-size:16px;line-height:24px;margin:16px 0;margin-top:-5px">
|
||||
<b>Project: </b> [Project Name]
|
||||
</p>
|
||||
<p
|
||||
style="font-size:16px;line-height:24px;margin:16px 0;margin-top:-5px">
|
||||
<b>Suspicious DNS: </b> [DNS_ENTRIES]
|
||||
</p>
|
||||
<p style="font-size:16px;line-height:24px;margin:16px 0">
|
||||
If this was you, there's nothing else you
|
||||
need to do.
|
||||
</p>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation" style="padding:20px;padding-top:0">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<td colspan="2" data-id="__react-email-column"
|
||||
style="display:flex;justify-content:center;width:100%">
|
||||
<a style="line-height:100%;text-decoration:none;display:inline-block;max-width:100%;mso-padding-alt:0px;background-color:#5680f8;border-radius:3px;color:#FFF;font-weight:bold;border:1px solid rgb(0,0,0, 0.1);cursor:pointer;padding:12px 30px 12px 30px"
|
||||
target="_blank" href="https://dashboard.litlyx.com"><span></span><span
|
||||
style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:9px">
|
||||
Go to Dashboard</span><span></span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation" style="padding:20px;padding-bottom:0">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<td data-id="__react-email-column">
|
||||
<h3>If this wasn't you..</h3>
|
||||
|
||||
<p>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).</p>
|
||||
|
||||
<p>You can also use <a href="https://www.whois.com/whois/"
|
||||
style="color: #D32F2F; text-decoration: none;">https://www.whois.com/whois/</a>
|
||||
to get the contact details of the webmaster or domain owner.</p>
|
||||
|
||||
<p>If webmasters don't respond or cooperate, <strong>you can file a
|
||||
DMCA complaint here:</strong> <a
|
||||
href="https://support.google.com/legal/answer/3110420?hl=en"
|
||||
style="color: #D32F2F; text-decoration: none;">https://support.google.com/legal/answer/3110420?hl=en</a>
|
||||
<strong>with Google to request the removal of the duplicate
|
||||
content from their search results.</strong></p>
|
||||
|
||||
<h3>Please refer to this for more information:</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://support.google.com/legal/answer/3110420?hl=en&sjid=14235884554806745995-AP&authuser=2"
|
||||
style="color: #D32F2F; text-decoration: none;">Report
|
||||
Content for Legal Reasons</a></li>
|
||||
<li><a href="https://www.dmca.com/FAQ/How-can-I-get-a-webpage-removed-from-Google-search-results"
|
||||
style="color: #D32F2F; text-decoration: none;">How can I
|
||||
get a webpage removed from Google search results?</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Your safety is our main priority.</p>
|
||||
|
||||
<p>Thank you for choosing Litlyx every day as your analytics tool!
|
||||
</p>
|
||||
|
||||
<p>Antonio,</p>
|
||||
<p>CEO | Litlyx</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="padding:45px 0 0 0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="https://react-email-demo-lpdmf0ryo-resend.vercel.app/static/yelp-footer.png"
|
||||
style="display:block;outline:none;border:none;text-decoration:none;max-width:100%"
|
||||
width="620" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="font-size:12px;line-height:24px;margin:16px 0;text-align:center;color:rgb(0,0,0, 0.7)">
|
||||
2024 © Litlyx. All rights reserved.
|
||||
<br>
|
||||
Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA: 17814721001- REA: RM-1743194
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
`
|
||||
152
emails/templates/AnomalyUsageEmail.ts
Normal file
152
emails/templates/AnomalyUsageEmail.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
export const ANOMALY_VISITS_EVENTS_EMAIL = `<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html dir="ltr" lang="en">
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
<!--$-->
|
||||
</head>
|
||||
|
||||
<body
|
||||
style='background-color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif'>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="max-width:37.5em">
|
||||
<tbody>
|
||||
<tr style="width:100%">
|
||||
<td>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="border:1px solid rgb(0,0,0, 0.1);border-radius:3px;overflow:hidden">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<img src="https://litlyx.com/images/locker2.png"
|
||||
style="display:block;outline:none;border:none;text-decoration:none;max-width:100%"
|
||||
width="620" />
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation" style="padding:20px;padding-bottom:0">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<td data-id="__react-email-column">
|
||||
<h1 style="font-size:32px;font-weight:bold;text-align:center">
|
||||
Dear user
|
||||
</h1>
|
||||
<h2 style="font-size:26px;font-weight:bold;text-align:center">
|
||||
Our AI Agent noticed a recent unexpected usage on your project
|
||||
on Litlyx.
|
||||
</h2>
|
||||
<p
|
||||
style="font-size:16px;line-height:24px;margin:16px 0;margin-top:-5px">
|
||||
<b>Project: </b> [Project Name]
|
||||
</p>
|
||||
<p
|
||||
style="font-size:16px;line-height:24px;margin:16px 0;margin-top:-5px">
|
||||
<b>Info: </b> [ENTRIES]
|
||||
</p>
|
||||
<p>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
|
||||
<strong>Litlyx Dashboard</strong>. You can analyze your recent
|
||||
traffic and event logs to identify any irregularities or
|
||||
potential issues.</p>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation" style="padding:20px;padding-top:0">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<td colspan="2" data-id="__react-email-column"
|
||||
style="display:flex;justify-content:center;width:100%">
|
||||
<a style="line-height:100%;text-decoration:none;display:inline-block;max-width:100%;mso-padding-alt:0px;background-color:#5680f8;border-radius:3px;color:#FFF;font-weight:bold;border:1px solid rgb(0,0,0, 0.1);cursor:pointer;padding:12px 30px 12px 30px"
|
||||
target="_blank"
|
||||
href="https://dashboard.litlyx.com"><span></span><span
|
||||
style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:9px">
|
||||
Go to Dashboard</span><span></span></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation" style="padding:20px;padding-bottom:0">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<td data-id="__react-email-column">
|
||||
|
||||
<h3>What can I do?</h3>
|
||||
|
||||
<p>To better understand the situation, you can:</p>
|
||||
|
||||
<ol>
|
||||
<li>Review your traffic sources to see where the visits or
|
||||
events are coming from.</li>
|
||||
<li>Check for any unexpected patterns, such as a high number of
|
||||
visits from unknown sources or abnormal event triggers.</li>
|
||||
<li>Check your code to find bugs on a specific action that is
|
||||
triggered in loops.</li>
|
||||
</ol>
|
||||
|
||||
<p>If you need help understanding this activity or have any
|
||||
concerns, feel free to reach out to our support team at <a
|
||||
href="mailto:help@litlyx.com"
|
||||
style="color: #D32F2F; text-decoration: none;"><strong>help@litlyx.com</strong></a>.
|
||||
We are here to assist you!</p>
|
||||
|
||||
<p><strong>Your safety and data integrity are our top
|
||||
priorities.</strong></p>
|
||||
|
||||
<p>Thank you for trusting Litlyx as your analytics tool!</p>
|
||||
|
||||
<p>Best regards,</p>
|
||||
|
||||
<p>Antonio,</p>
|
||||
<p>CEO | Litlyx</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="padding:45px 0 0 0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="https://react-email-demo-lpdmf0ryo-resend.vercel.app/static/yelp-footer.png"
|
||||
style="display:block;outline:none;border:none;text-decoration:none;max-width:100%"
|
||||
width="620" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="font-size:12px;line-height:24px;margin:16px 0;text-align:center;color:rgb(0,0,0, 0.7)">
|
||||
2024 © Litlyx. All rights reserved.
|
||||
<br>
|
||||
Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA: 17814721001- REA: RM-1743194
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
`
|
||||
44
emails/templates/ConfirmEmail.ts
Normal file
44
emails/templates/ConfirmEmail.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
export const CONFIRM_EMAIL = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Confirm your email</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color:#f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">Confirm your email on Litlyx</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color:#4a4a4a; font-size:16px;">
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Thanks for signing up on Litlyx! Please confirm your email address by clicking the button below.
|
||||
</p>
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
We hope to see you soon!
|
||||
</p>
|
||||
<a href="[CONFIRM_LINK]"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px;font-weight: bold;"
|
||||
target="_blank">
|
||||
Confirm Email
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
37
emails/templates/ForgotPasswordEmail.ts
Normal file
37
emails/templates/ForgotPasswordEmail.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
export const FORGOT_PASSWORD_EMAIL = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Reset Your Password</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color: #f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width: 600px; margin: auto; background-color: #ffffff; border-radius: 8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size: 20px; color: #333333; margin: 0;">Forgot your password?</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: center; color: #4a4a4a; font-size: 16px;">
|
||||
<p style="margin: 0 0 20px;">Don't worry! Click the button below to set a new password for your account:</p>
|
||||
<a href="[LINK]"
|
||||
style="display: inline-block; background-color: #0a0a0a; color: #ffffff; text-decoration: none; padding: 12px 24px; border-radius: 8px; font-weight: bold;">
|
||||
Reset Password</a>
|
||||
<p style="margin-top: 20px; font-size: 14px; color: #888888;"><strong>Note:</strong> This link will expire in 3
|
||||
hours.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
112
emails/templates/Limit50Email.ts
Normal file
112
emails/templates/Limit50Email.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
export const LIMIT_50_EMAIL = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
</head>
|
||||
|
||||
<body
|
||||
style='background-color:#ffffff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif'>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="max-width:100%;margin:0 auto;padding:20px 0 48px;width:580px">
|
||||
<tbody>
|
||||
<tr style="width:100%">
|
||||
<td>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img alt="Founder" height="96"
|
||||
src="https://litlyx.com/images/founder.jpg"
|
||||
style="display:block;outline:none;border:none;text-decoration:none;margin:0 auto;margin-bottom:16px;border-radius:50%"
|
||||
width="96" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="padding-bottom:20px">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<p
|
||||
style="font-size:32px;line-height:1.3;margin:16px 0;font-weight:700;color:#484848">
|
||||
You’ve Reached 50% of Your Litlyx's Tracking Limits
|
||||
</p>
|
||||
<p
|
||||
style="font-size:18px;line-height:1.4;margin:16px 0;color:#484848;padding:24px;background-color:#f2f3f3;border-radius:4px">
|
||||
To avoid losing precious data, please remember to monitor your usage
|
||||
on the <strong>Litlyx Dashboard</strong>. You can find your current
|
||||
usage details in your account section.
|
||||
</p>
|
||||
|
||||
<p>If you need more data collection storage, you may consider upgrading
|
||||
your plan to get additional benefits and ensure uninterrupted data
|
||||
collection.</p>
|
||||
|
||||
<p>Feel free to reply to this email or contact us at <a
|
||||
href="mailto:help@litlyx.com"
|
||||
style="color: #FF5733; text-decoration: none;">help@litlyx.com</a>
|
||||
if you have any questions or need assistance.</p>
|
||||
|
||||
<p>Thank you for choosing Litlyx every day as your analytics tool.</p>
|
||||
|
||||
<p>Have a nice day!</p>
|
||||
|
||||
<p>Antonio,</p>
|
||||
<p>CEO at Litlyx</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/"
|
||||
style="line-height:100%;text-decoration:none;display:block;max-width:100%;mso-padding-alt:0px;background-color:#5680f8;border-radius:3px;color:#fff;font-size:18px;padding-top:19px;padding-bottom:19px;text-align:center;width:100%;padding:19px 0px 19px 0px"
|
||||
target="_blank"><span>
|
||||
|
||||
</span><span
|
||||
style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:14.25px">Go to Dashboard</span><span></span></a>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr
|
||||
style="width:100%;border:none;border-top:1px solid #eaeaea;border-color:#cccccc;margin:20px 0" />
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<p
|
||||
style="font-size:14px;line-height:24px;margin:16px 0;color:#9ca299;margin-bottom:10px">
|
||||
2025 © Litlyx. All rights reserved.
|
||||
<br>
|
||||
Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA:
|
||||
17814721001- REA: RM-1743194
|
||||
</p>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--/$-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
`
|
||||
112
emails/templates/Limit90Email.ts
Normal file
112
emails/templates/Limit90Email.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
export const LIMIT_90_EMAIL = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
</head>
|
||||
|
||||
<body
|
||||
style='background-color:#ffffff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif'>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="max-width:100%;margin:0 auto;padding:20px 0 48px;width:580px">
|
||||
<tbody>
|
||||
<tr style="width:100%">
|
||||
<td>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img alt="Founder" height="96"
|
||||
src="https://litlyx.com/images/founder.jpg"
|
||||
style="display:block;outline:none;border:none;text-decoration:none;margin:0 auto;margin-bottom:16px;border-radius:50%"
|
||||
width="96" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="padding-bottom:20px">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<p
|
||||
style="font-size:32px;line-height:1.3;margin:16px 0;font-weight:700;color:#484848">
|
||||
You’ve Reached 90% of Your Litlyx's Tracking Limits
|
||||
</p>
|
||||
<p
|
||||
style="font-size:18px;line-height:1.4;margin:16px 0;color:#484848;padding:24px;background-color:#f2f3f3;border-radius:4px">
|
||||
To avoid losing precious data, please remember to monitor your usage
|
||||
on the <strong>Litlyx Dashboard</strong>. You can find your current
|
||||
usage details in your account section.
|
||||
</p>
|
||||
|
||||
<p>If you need more data collection storage, you may consider upgrading
|
||||
your plan to get additional benefits and ensure uninterrupted data
|
||||
collection.</p>
|
||||
|
||||
<p>Feel free to reply to this email or contact us at <a
|
||||
href="mailto:help@litlyx.com"
|
||||
style="color: #FF5733; text-decoration: none;">help@litlyx.com</a>
|
||||
if you have any questions or need assistance.</p>
|
||||
|
||||
<p>Thank you for choosing Litlyx every day as your analytics tool.</p>
|
||||
|
||||
<p>Have a nice day!</p>
|
||||
|
||||
<p>Antonio,</p>
|
||||
<p>CEO at Litlyx</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/"
|
||||
style="line-height:100%;text-decoration:none;display:block;max-width:100%;mso-padding-alt:0px;background-color:#5680f8;border-radius:3px;color:#fff;font-size:18px;padding-top:19px;padding-bottom:19px;text-align:center;width:100%;padding:19px 0px 19px 0px"
|
||||
target="_blank"><span>
|
||||
|
||||
</span><span
|
||||
style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:14.25px">Go to Dashboard</span><span></span></a>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr
|
||||
style="width:100%;border:none;border-top:1px solid #eaeaea;border-color:#cccccc;margin:20px 0" />
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<p
|
||||
style="font-size:14px;line-height:24px;margin:16px 0;color:#9ca299;margin-bottom:10px">
|
||||
2025 © Litlyx. All rights reserved.
|
||||
<br>
|
||||
Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA:
|
||||
17814721001- REA: RM-1743194
|
||||
</p>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--/$-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
`
|
||||
127
emails/templates/LimitMaxEmail.ts
Normal file
127
emails/templates/LimitMaxEmail.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
export const LIMIT_MAX_EMAIL = `<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
</head>
|
||||
|
||||
<body
|
||||
style='background-color:#ffffff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif'>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="max-width:100%;margin:0 auto;padding:20px 0 48px;width:580px">
|
||||
<tbody>
|
||||
<tr style="width:100%">
|
||||
<td>
|
||||
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<img alt="Founder" height="96"
|
||||
src="https://litlyx.com/images/founder.jpg"
|
||||
style="display:block;outline:none;border:none;text-decoration:none;margin:0 auto;margin-bottom:16px;border-radius:50%"
|
||||
width="96" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||
style="padding-bottom:20px">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<p
|
||||
style="font-size:32px;line-height:1.3;margin:16px 0;font-weight:700;color:#484848">
|
||||
You’ve Reached Your Litlyx's Tracking Limits
|
||||
</p>
|
||||
<p
|
||||
style="font-size:18px;line-height:1.4;margin:16px 0;color:#484848;padding:24px;background-color:#ffbb03;border-radius:4px">
|
||||
<strong>Litlyx has stopped collecting data for your project.</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
To help you avoid losing valuable insights, we recommend keeping an
|
||||
eye on your usage via the Litlyx Dashboard.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can view your current usage details under Settings > Billing
|
||||
Tab.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you need additional storage for data collection, consider
|
||||
upgrading your plan to unlock more benefits and ensure uninterrupted
|
||||
service. You can find out more here: <a href="https://litlyx.com/pricing-selfhosted">Our pricing</a>
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If you have any questions or need assistance, feel free to reply to
|
||||
this email or contact us at <a href="mailto:help@litlyx.com"
|
||||
style="color: #FF5733; text-decoration: none;">help@litlyx.com</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Have a great day!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Antonio,
|
||||
CEO at Litlyx
|
||||
</p>
|
||||
|
||||
|
||||
<a href="https://dashboard.litlyx.com/"
|
||||
style="line-height:100%;text-decoration:none;display:block;max-width:100%;mso-padding-alt:0px;background-color:#5680f8;border-radius:3px;color:#fff;font-size:18px;padding-top:19px;padding-bottom:19px;text-align:center;width:100%;padding:19px 0px 19px 0px"
|
||||
target="_blank"><span>
|
||||
|
||||
</span><span
|
||||
style="max-width:100%;display:inline-block;line-height:120%;mso-padding-alt:0px;mso-text-raise:14.25px">Go
|
||||
to Dashboard</span><span></span></a>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr
|
||||
style="width:100%;border:none;border-top:1px solid #eaeaea;border-color:#cccccc;margin:20px 0" />
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table align="center" width="100%" border="0" cellpadding="0" cellspacing="0"
|
||||
role="presentation">
|
||||
<tbody style="width:100%">
|
||||
<tr style="width:100%">
|
||||
<p
|
||||
style="font-size:14px;line-height:24px;margin:16px 0;color:#9ca299;margin-bottom:10px">
|
||||
2025 © Litlyx. All rights reserved.
|
||||
<br>
|
||||
Litlyx S.R.L. - Viale Tirreno, 187 - 00141 Rome - P.IVA:
|
||||
17814721001- REA: RM-1743194
|
||||
</p>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--/$-->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
`
|
||||
47
emails/templates/ProjectInviteEmail.ts
Normal file
47
emails/templates/ProjectInviteEmail.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
export const PROJECT_INVITE_EMAIL = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>You're invited to a Litlyx workspace</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color:#f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">You're invited to the Litlyx workspace
|
||||
<strong>[Workspace_Name]</strong>!
|
||||
</h2>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color:#4a4a4a; font-size:16px;">
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Join now by clicking the button below.
|
||||
</p>
|
||||
|
||||
<a href="[LINK]"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px;font-weight: bold;"
|
||||
target="_blank">
|
||||
Join the Workspace
|
||||
</a>
|
||||
|
||||
<p style="font-size:14px; line-height:1.6; color:#777777; margin-top:24px;">
|
||||
Need help? Reach out anytime at <a href="mailto:help@litlyx.com" style="color:#007BFF;">help@litlyx.com</a>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
47
emails/templates/ProjectInviteEmailNoAccount.ts
Normal file
47
emails/templates/ProjectInviteEmailNoAccount.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
export const PROJECT_INVITE_EMAIL_NO_ACCOUNT = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>You're invited to a Litlyx workspace</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color:#f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">You're invited to the Litlyx workspace
|
||||
<strong>[Workspace_Name]</strong>!
|
||||
</h2>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color:#4a4a4a; font-size:16px;">
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Join now by clicking the button below.
|
||||
</p>
|
||||
|
||||
<a href="[Link]"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px;font-weight: bold;"
|
||||
target="_blank">
|
||||
Join the Workspace
|
||||
</a>
|
||||
|
||||
<p style="font-size:14px; line-height:1.6; color:#777777; margin-top:24px;">
|
||||
Need help? Reach out anytime at <a href="mailto:help@litlyx.com" style="color:#007BFF;">help@litlyx.com</a>.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
52
emails/templates/PurchaseEmail.ts
Normal file
52
emails/templates/PurchaseEmail.ts
Normal file
File diff suppressed because one or more lines are too long
78
emails/templates/PurchaseSelfhostEmail.ts
Normal file
78
emails/templates/PurchaseSelfhostEmail.ts
Normal file
File diff suppressed because one or more lines are too long
62
emails/templates/free_trial/1-FreeTrialStarted.ts
Normal file
62
emails/templates/free_trial/1-FreeTrialStarted.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
export const N1_FREE_TRIAL_STARTED = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Your free trial has started!</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color: #f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width: 600px; margin: auto; background-color: #ffffff; border-radius: 8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size: 20px; color: #333333; margin: 0;">Your free trial has started!</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color: #4a4a4a; font-size: 16px;">
|
||||
<p style="font-size:16px;line-height:1.6;color:#484848;">
|
||||
Welcome to Litlyx! Your 30-day free trial has officially started. You now have full access to the Litlyx
|
||||
dashboard and premium features.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px;line-height:1.6;color:#484848;">
|
||||
We’ll send you a reminder before your trial ends. Once the 30 days are over, dashboard access will be paused
|
||||
unless you upgrade.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px;line-height:1.6;color:#484848;">
|
||||
Are you using WordPress, Shopify, Google Tag Manager, or a modern framework? Head
|
||||
over to <a href="http://docs.litlyx.com" style="color: #007BFF;">our docs</a> for full setup
|
||||
instructions. If you need help we're always here to help you.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px;line-height:1.6;color:#484848;">
|
||||
Take this time to explore the platform, set up your tracking, and see what insights Litlyx can offer for your
|
||||
projects.
|
||||
</p>
|
||||
<p style="font-size:16px;line-height:1.6;color:#484848;">
|
||||
Let’s make analytics the simplest part of your journey.
|
||||
</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/"
|
||||
style="line-height:100%;text-decoration:none;display:block;max-width:100%;background-color:#0a0a0a;border-radius:16px;color:#fff;font-size:14px;padding-top:19px;padding-bottom:19px;text-align:center;width:100%;padding:19px 0px 19px 0px"
|
||||
target="_blank">
|
||||
<span style="max-width:100%;display:inline-block;line-height:120%;font-weight: bold;">
|
||||
Explore Litlyx's Dashboard
|
||||
</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
60
emails/templates/free_trial/2-FreeTrial10DaysIn.ts
Normal file
60
emails/templates/free_trial/2-FreeTrial10DaysIn.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
export const N2_FREE_TRIAL_10_DAYS_IN = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Get even more out of Litlyx</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color: #f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width: 600px; margin: auto; background-color: #ffffff; border-radius: 8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size: 20px; color: #333333; margin: 0;">You're tracking your stats with Litlyx 🎉</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color: #4a4a4a; font-size: 16px;">
|
||||
<p style="font-size:16px;line-height:1.6;color:#484848;">
|
||||
Litlyx is tracking your website or web app stats, without compromising your visitors' experience or privacy.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px;line-height:1.6;color:#484848;">
|
||||
Here’s how to get even more out of your Litlyx setup:
|
||||
</p>
|
||||
|
||||
<ul style="font-size:16px;line-height:1.6;color:#484848; padding-left: 20px;">
|
||||
<li>Set up <a href="https://docs.litlyx.com/custom-events"><strong>custom events</strong></a> to track key
|
||||
user actions.</li>
|
||||
<li>Running an ecommerce site on Shopify? <a href="https://docs.litlyx.com/techs/shopify"><strong>Read our
|
||||
docs</strong></a>.</li>
|
||||
<li>Ask our <strong>AI</strong> for insights on marketing, product, and growth.</li>
|
||||
</ul>
|
||||
|
||||
<p style="font-size:16px;line-height:1.6;color:#484848;">
|
||||
Check your dashboard now to explore traffic insights at a glance.
|
||||
</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/"
|
||||
style="line-height:100%;text-decoration:none;display:block;max-width:100%;background-color:#0a0a0a;border-radius:16px;color:#fff;font-size:14px;padding-top:19px;padding-bottom:19px;text-align:center;width:100%;padding:19px 0px 19px 0px"
|
||||
target="_blank">
|
||||
<span style="max-width:100%;display:inline-block;line-height:120%;font-weight: bold;">
|
||||
Go to Litlyx Dashboard
|
||||
</span>
|
||||
</a>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
53
emails/templates/free_trial/3-FreeTrial1WeekLeft.ts
Normal file
53
emails/templates/free_trial/3-FreeTrial1WeekLeft.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
export const N3_FREE_TRIAL_1_WEEK_LEFT = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Your Litlyx trial is ending soon</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color: #f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">Your Litlyx trial ends soon.</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color: #4a4a4a; font-size: 16px;">
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Time flies when we have fun! Your 30-day free trial of Litlyx will end next week.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
We hope you're enjoying seeing your website or web app stats in a fast, privacy-friendly dashboard, without
|
||||
cookie banners or
|
||||
loading delays.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
To keep your insights flowing, just upgrade your account before the trial ends.
|
||||
</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/plans"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px;font-weight: bold;"
|
||||
target="_blank">
|
||||
Upgrade your plan
|
||||
</a>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
43
emails/templates/free_trial/4-FreeTrialEndsTomorrow.ts
Normal file
43
emails/templates/free_trial/4-FreeTrialEndsTomorrow.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
export const N4_FREE_TRIAL_ENDS_TOMORROW = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Your Litlyx trial ends tomorrow</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color:#f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">Your Litlyx trial ends tomorrow.</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color: #4a4a4a; font-size: 16px;">
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Thanks for exploring Litlyx... a simple, fast, and privacy-first way to track your website or web app. Your free 30-day
|
||||
trial ends tomorrow, but you can keep your dashboard and insights by upgrading to a paid plan.
|
||||
</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/plans"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px;font-weight: bold;"
|
||||
target="_blank">
|
||||
Upgrade now
|
||||
</a>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
41
emails/templates/free_trial/5-FreeTrialEndsToday.ts
Normal file
41
emails/templates/free_trial/5-FreeTrialEndsToday.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
export const N5_FREE_TRIAL_ENDS_TODAY = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Your Litlyx trial ends today</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color:#f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">Your Litlyx trial ends today</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color: #4a4a4a; font-size: 16px;">
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Thanks for exploring Litlyx... a simple, fast, and privacy-first way to track your website or web app. Your free 30-day
|
||||
trial ends today, but you can keep your dashboard and insights by upgrading to a paid plan.
|
||||
</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/plans"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px; font-weight: bold;"
|
||||
target="_blank">
|
||||
Upgrade now
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
49
emails/templates/free_trial/6-FreeTrialHasEnded.ts
Normal file
49
emails/templates/free_trial/6-FreeTrialHasEnded.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
export const N6_FREE_TRIAL_HAS_ENDED = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Your Litlyx trial has ended</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color:#f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">Your Litlyx trial has ended</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color: #4a4a4a; font-size: 16px;">
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Your 30-day free trial with Litlyx has ended, and we've temporarily restricted access to your dashboard.
|
||||
<strong>However, we will continue tracking your data for an additional 14 days</strong> to give you time to
|
||||
upgrade.
|
||||
After this period, tracking will stop to help us reduce server costs and maintain sustainability.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
<strong>All the data you've collected is safe and securely stored in our database</strong>.
|
||||
Please note that data may be deleted after a period of inactivity.
|
||||
</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/plans"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px; font-weight: bold;"
|
||||
target="_blank">
|
||||
Upgrade your plan
|
||||
</a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
50
emails/templates/free_trial/7-LitlyxWillStopCollecting.ts
Normal file
50
emails/templates/free_trial/7-LitlyxWillStopCollecting.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
export const N7_LITLYX_WILL_STOP_COLLECTING = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Tracking will stop in 2 days</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color:#f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">Tracking will stop in 2 days</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color: #4a4a4a; font-size: 16px;">
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Your extended grace period is almost over.
|
||||
<strong>In just 2 days, Litlyx will stop collecting data from your domains.</strong>
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
This means no new events will be tracked, and your reports will no longer stay up to date.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
<strong>Your existing data is still safe</strong>, but we recommend upgrading now to avoid any disruption.
|
||||
</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/plans"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px; font-weight: bold;"
|
||||
target="_blank">
|
||||
Upgrade now to keep tracking
|
||||
</a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
50
emails/templates/free_trial/8-LitlyxHasStopGracePeriod.ts
Normal file
50
emails/templates/free_trial/8-LitlyxHasStopGracePeriod.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
export const N8_LITLYX_HAS_STOP_GRACE_PERIOD = `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Your Litlyx Grace Period Has Ended</title>
|
||||
</head>
|
||||
|
||||
<body style="margin:0; padding:0; font-family: Arial, sans-serif; background-color:#f9f9f9;">
|
||||
<table align="center" cellpadding="0" cellspacing="0" width="100%"
|
||||
style="max-width:600px; margin:auto; background-color:#ffffff; border-radius:8px;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 20px 10px;">
|
||||
<img src="https://static.litlyx.com/icon.png" alt="" width="48px" height="48px">
|
||||
<h2 style="font-size:20px; color:#333333; margin:0;">Your grace period has ended</h2>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px 30px; text-align: left; color: #4a4a4a; font-size: 16px;">
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
Your 14-day grace period has officially ended.
|
||||
<strong>Litlyx has now stopped collecting data from your domains.</strong>
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
This means no new events are being tracked, and your reports will no longer update.
|
||||
</p>
|
||||
|
||||
<p style="font-size:16px; line-height:1.6; color:#484848;">
|
||||
<strong>Your existing data is still safe</strong> and securely stored, but to resume tracking and regain full dashboard access, please upgrade your plan.
|
||||
</p>
|
||||
|
||||
<a href="https://dashboard.litlyx.com/plans"
|
||||
style="display:block; background-color:#0a0a0a; color:#ffffff; text-align:center; border-radius:16px; text-decoration:none; font-size:14px; padding:16px; margin-top:20px; font-weight: bold;"
|
||||
target="_blank">
|
||||
Upgrade now to resume tracking
|
||||
</a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 20px 40px; text-align: center; font-size: 12px; color: #777777;">
|
||||
<p style="margin-top: 10px;">2025 © Litlyx - Analytics reimagined. All rights reserved.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>`
|
||||
16
emails/tsconfig.json
Normal file
16
emails/tsconfig.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext",
|
||||
"target": "ESNext",
|
||||
"outDir": "dist",
|
||||
"strictNullChecks": true,
|
||||
"moduleResolution": "nodenext",
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"./**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user