diff --git a/dist/src/controllers/account.js b/dist/src/controllers/account.js index 260ccc2..3e7a0cd 100644 --- a/dist/src/controllers/account.js +++ b/dist/src/controllers/account.js @@ -36,8 +36,8 @@ Object.defineProperty(exports, "__esModule", { value: true }); const account_1 = __importDefault(require("../models/account")); const block_1 = __importDefault(require("../models/block")); const crm_1 = __importDefault(require("../services/crm")); -const mailer_1 = __importDefault(require("../services/mailer")); const logger_1 = __importDefault(require("../services/logger")); +const eventTracker_1 = __importDefault(require("../services/eventTracker")); const recaptcha = __importStar(require("../services/recaptcha")); // Logger setup const logger = new logger_1.default('Account Controller'); @@ -54,7 +54,7 @@ class AccountController { yield _account.store(); const { contactEmail } = params; void crm_1.default.addNewUser(contactEmail, _account.uuid); - void mailer_1.default.sendWelcomeEmail(contactEmail, _account.uuid, _account.name); + void eventTracker_1.default.trackSignup(contactEmail, _account.uuid, _account.name); logger.logAndSlack(`Account created for ${contactEmail}: ${_account.uuid}`); return _account.uuid; } diff --git a/dist/src/interfaces/plunkEvent.js b/dist/src/interfaces/plunkEvent.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/dist/src/interfaces/plunkEvent.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/src/services/__mocks__/eventTracker.js b/dist/src/services/__mocks__/eventTracker.js new file mode 100644 index 0000000..5e4519e --- /dev/null +++ b/dist/src/services/__mocks__/eventTracker.js @@ -0,0 +1,14 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const EventTracker = { + trackSignup: jest.fn(() => __awaiter(void 0, void 0, void 0, function* () { })), +}; +module.exports = EventTracker; diff --git a/dist/src/services/eventTracker.js b/dist/src/services/eventTracker.js new file mode 100644 index 0000000..a79e8d5 --- /dev/null +++ b/dist/src/services/eventTracker.js @@ -0,0 +1,55 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const axios_1 = __importDefault(require("axios")); +const logger_1 = __importDefault(require("./logger")); +class EventTracker { + constructor(plunkEvent) { + this.apiKey = process.env.EVENT_TRACKING_API_KEY; + this.plunkEndpoint = 'https://next-api.useplunk.com/v1/track'; + this.logger = new logger_1.default('Event Tracker'); + const { email, event, data } = plunkEvent; + this.email = email; + this.event = event; + this.data = data; + } + static trackSignup(email, pantryID, pantryName) { + const _event = { + email, + event: 'pantry.created', + data: { pantryID, pantryName }, + }; + void new EventTracker(_event).track(); + } + track() { + return __awaiter(this, void 0, void 0, function* () { + try { + yield (0, axios_1.default)({ + method: 'POST', + headers: { + 'Authorization': `Bearer ${this.apiKey}`, + 'Content-Type': 'application/json', + }, + url: this.plunkEndpoint, + data: { email: this.email, event: this.event, data: this.data }, + }); + this.logger.info(`Successfully tracked event ${this.event} for ${this.email}`); + } + catch (error) { + this.logger.info(`Failed to track event ${this.event} for ${this.email}: ${error}`); + } + }); + } +} +exports.default = EventTracker; diff --git a/env.sample b/env.sample index 6f60b4b..e0c963c 100644 --- a/env.sample +++ b/env.sample @@ -5,6 +5,7 @@ SLACK_LOG_WEBHOOK="string" CRYPTO_KEY="32 Byte string" CRYPTO_IV="16 Byte string" MAILER_API_KEY='string' +EVENT_TRACKING_API_KEY='string' WELCOME_TEMPLATE_ID='string ACCOUNT_ERRORS_EMAIL_ID='string' AIRTABLE_API_TOKEN='string' diff --git a/src/controllers/account.ts b/src/controllers/account.ts index 7beb757..45efac5 100644 --- a/src/controllers/account.ts +++ b/src/controllers/account.ts @@ -4,8 +4,8 @@ import Account from '../models/account' import Block from '../models/block' import Crm from '../services/crm' -import Mailer from '../services/mailer' import logService from '../services/logger' +import EventTracker from '../services/eventTracker' import * as recaptcha from '../services/recaptcha' // Interfaces @@ -29,7 +29,7 @@ class AccountController { const { contactEmail } = params void Crm.addNewUser(contactEmail, _account.uuid) - void Mailer.sendWelcomeEmail(contactEmail, _account.uuid, _account.name) + void EventTracker.trackSignup(contactEmail, _account.uuid, _account.name) logger.logAndSlack(`Account created for ${contactEmail}: ${_account.uuid}`) return _account.uuid diff --git a/src/interfaces/plunkEvent.ts b/src/interfaces/plunkEvent.ts new file mode 100644 index 0000000..de96bff --- /dev/null +++ b/src/interfaces/plunkEvent.ts @@ -0,0 +1,8 @@ +export interface IPlunkEvent { + email: string, + event: string, + data: { + pantryID: string, + pantryName: string + } +} diff --git a/src/services/__mocks__/eventTracker.ts b/src/services/__mocks__/eventTracker.ts new file mode 100644 index 0000000..2bbd200 --- /dev/null +++ b/src/services/__mocks__/eventTracker.ts @@ -0,0 +1,5 @@ +const EventTracker = { + trackSignup: jest.fn(async () => { }), +} + +export = EventTracker diff --git a/src/services/eventTracker.ts b/src/services/eventTracker.ts new file mode 100644 index 0000000..cf046e9 --- /dev/null +++ b/src/services/eventTracker.ts @@ -0,0 +1,50 @@ +import axios from 'axios' + +import { IPlunkEvent } from '../interfaces/plunkEvent' +import logService from './logger' + +class EventTracker { + private apiKey: string = process.env.EVENT_TRACKING_API_KEY + private plunkEndpoint: string = 'https://next-api.useplunk.com/v1/track' + private logger = new logService('Event Tracker') + private email: string + private event: string + private data: unknown + + public constructor(plunkEvent: IPlunkEvent) { + const { email, event, data } = plunkEvent + this.email = email + this.event = event + this.data = data + } + + public static trackSignup(email: string, pantryID: string, + pantryName: string): void { + const _event: IPlunkEvent = { + email, + event: 'pantry.created', + data: { pantryID, pantryName }, + } + void new EventTracker(_event).track() + } + + + public async track(): Promise { + try { + await axios({ + method: 'POST', + headers: { + 'Authorization': `Bearer ${this.apiKey}`, + 'Content-Type': 'application/json', + }, + url: this.plunkEndpoint, + data: { email: this.email, event: this.event, data: this.data }, + }) + this.logger.info(`Successfully tracked event ${this.event} for ${this.email}`) + } catch (error) { + this.logger.info(`Failed to track event ${this.event} for ${this.email}: ${error}`) + } + } +} + +export default EventTracker diff --git a/tests/controllers/account.test.ts b/tests/controllers/account.test.ts index 840ffc0..2d31b1f 100644 --- a/tests/controllers/account.test.ts +++ b/tests/controllers/account.test.ts @@ -2,12 +2,12 @@ import AccountController from '../../src/controllers/account' import Account from '../../src/models/account' import Crm from '../../src/services/crm' -import Mailer from '../../src/services/mailer' +import EventTracker from '../../src/services/eventTracker' import * as dataStore from '../../src/services/dataStore' import * as recaptcha from '../../src/services/recaptcha' jest.mock('../../src/services/dataStore') -jest.mock('../../src/services/mailer') +jest.mock('../../src/services/eventTracker') jest.mock('../../src/services/crm') jest.mock('../../src/services/recaptcha') @@ -61,8 +61,8 @@ describe('When creating an account', () => { expect(_uuid).toBeDefined() }) - it ('sends a welcome email', async () => { - const _spy = jest.spyOn(Mailer, 'sendWelcomeEmail') + it ('tracks signup as an event', async () => { + const _spy = jest.spyOn(EventTracker, 'trackSignup') const _uuid: string = await AccountController.create(_newAccountParams)