/ src / reports / purchase-confirmation.js
purchase-confirmation.js
  1  /**
  2   * Purchase Confirmation Email
  3   *
  4   * Sends a confirmation email when a new purchase is ingested from the CF Worker.
  5   * Uses Resend following the same pattern as src/outreach/email.js.
  6   */
  7  
  8  import { Resend } from 'resend';
  9  import Logger from '../utils/logger.js';
 10  import '../utils/load-env.js';
 11  
 12  const logger = new Logger('PurchaseConfirmation');
 13  
 14  /**
 15   * Send a purchase confirmation email
 16   * @param {Object} params
 17   * @param {string} params.email - Customer email
 18   * @param {string} params.orderId - PayPal order ID
 19   * @param {number} params.amount - Amount in smallest currency unit (cents)
 20   * @param {string} params.currency - ISO 4217 currency code
 21   * @param {string} params.url - Website URL being audited
 22   */
 23  export async function sendConfirmationEmail({ email, orderId, amount, currency, url, product = 'full_audit' }) {
 24    const apiKey = process.env.RESEND_API_KEY;
 25    if (!apiKey) {
 26      logger.warn('RESEND_API_KEY not configured, skipping confirmation email');
 27      return { success: false, reason: 'no_api_key' };
 28    }
 29  
 30    const senderEmail = process.env.AUDITANDFIX_SENDER_EMAIL || 'reports@auditandfix.com';
 31    const resend = new Resend(apiKey);
 32  
 33    // Format amount for display
 34    const formattedAmount = `${currency} ${(amount / 100).toFixed(2)}`;
 35  
 36    // Extract domain from URL
 37    let domain;
 38    try {
 39      domain = new URL(url).hostname;
 40    } catch {
 41      domain = url;
 42    }
 43  
 44    const isQuickFixes = product === 'quick_fixes';
 45    const isAuditFix = product === 'audit_fix';
 46  
 47    const html = `
 48  <!DOCTYPE html>
 49  <html>
 50  <head>
 51    <meta charset="utf-8">
 52    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 53  </head>
 54  <body style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: #2d3748; max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f7fafc;">
 55    <div style="background: #1a365d; color: white; padding: 30px; border-radius: 8px 8px 0 0; text-align: center;">
 56      <h1 style="margin: 0; font-size: 24px;">Order Confirmed</h1>
 57      <p style="margin: 10px 0 0; opacity: 0.9; font-size: 14px;">${isQuickFixes ? 'Your Quick Fixes Report is Being Prepared' : isAuditFix ? 'Your Audit + Implementation is Being Prepared' : 'Your CRO Audit Report is Being Prepared'}</p>
 58    </div>
 59  
 60    <div style="background: white; padding: 30px; border-radius: 0 0 8px 8px; border: 1px solid #e2e8f0; border-top: none;">
 61      <p>Thank you for your purchase!</p>
 62  
 63      <div style="background: #f7fafc; padding: 20px; border-radius: 6px; margin: 20px 0;">
 64        <table style="width: 100%; border-collapse: collapse;">
 65          <tr>
 66            <td style="padding: 8px 0; color: #718096;">Order ID</td>
 67            <td style="padding: 8px 0; text-align: right; font-weight: 600;">${orderId}</td>
 68          </tr>
 69          <tr>
 70            <td style="padding: 8px 0; color: #718096;">Website</td>
 71            <td style="padding: 8px 0; text-align: right; font-weight: 600;">${domain}</td>
 72          </tr>
 73          <tr>
 74            <td style="padding: 8px 0; color: #718096;">Amount Paid</td>
 75            <td style="padding: 8px 0; text-align: right; font-weight: 600;">${formattedAmount}</td>
 76          </tr>
 77        </table>
 78      </div>
 79  
 80      <h3 style="color: #1a365d; margin-top: 25px;">What happens next?</h3>
 81      ${isQuickFixes ? `
 82      <ol style="padding-left: 20px; color: #4a5568;">
 83        <li style="margin-bottom: 8px;">Our system captures a full-page screenshot of your website</li>
 84        <li style="margin-bottom: 8px;">AI analyzes your 5 worst-scoring conversion factors</li>
 85        <li style="margin-bottom: 8px;">A PDF with screenshot annotations and fix instructions is generated</li>
 86        <li style="margin-bottom: 8px;">Your report will be delivered to this email <strong>today</strong></li>
 87      </ol>
 88      <p style="margin-top: 25px; padding: 15px; background: #ebf8ff; border-radius: 6px; color: #2b6cb0; font-size: 14px;">
 89        Please check your spam/junk folder if you don't see the report today.
 90      </p>` : isAuditFix ? `
 91      <ol style="padding-left: 20px; color: #4a5568;">
 92        <li style="margin-bottom: 8px;">Our system captures a full-page screenshot of your website</li>
 93        <li style="margin-bottom: 8px;">AI analyzes 10 conversion factors with zoomed-in problem screenshots</li>
 94        <li style="margin-bottom: 8px;">A comprehensive PDF report is generated with prioritized recommendations</li>
 95        <li style="margin-bottom: 8px;">Your report will be delivered to this email within <strong>24 hours</strong></li>
 96        <li style="margin-bottom: 8px;">We implement your top 3 fixes with before/after screenshots within <strong>48 hours</strong></li>
 97      </ol>
 98      <p style="margin-top: 25px; padding: 15px; background: #ebf8ff; border-radius: 6px; color: #2b6cb0; font-size: 14px;">
 99        Please check your spam/junk folder if you don't see the report within 48 hours.
100      </p>` : `
101      <ol style="padding-left: 20px; color: #4a5568;">
102        <li style="margin-bottom: 8px;">Our system captures a full-page screenshot of your website</li>
103        <li style="margin-bottom: 8px;">AI analyzes 10 conversion factors with zoomed-in problem screenshots</li>
104        <li style="margin-bottom: 8px;">A comprehensive PDF report is generated with prioritized recommendations</li>
105        <li style="margin-bottom: 8px;">Your report will be delivered to this email within <strong>24 hours</strong></li>
106      </ol>
107      <p style="margin-top: 25px; padding: 15px; background: #ebf8ff; border-radius: 6px; color: #2b6cb0; font-size: 14px;">
108        Please check your spam/junk folder if you don't see the report within 24 hours.
109      </p>`}
110  
111      <p style="margin-top: 25px; color: #718096; font-size: 13px;">
112        Questions? Reply to this email or contact us at <a href="mailto:${senderEmail}" style="color: #3182ce;">${senderEmail}</a>
113      </p>
114    </div>
115  
116    <p style="text-align: center; color: #a0aec0; font-size: 12px; margin-top: 20px;">
117      Audit&Fix CRO Reports
118    </p>
119  </body>
120  </html>`.trim();
121  
122    try {
123      const result = await resend.emails.send({
124        from: `Audit&Fix <${senderEmail}>`,
125        to: email,
126        subject: isQuickFixes
127          ? `Order Confirmed — Your Quick Fixes Report for ${domain} is Being Prepared`
128          : isAuditFix
129            ? `Order Confirmed — Your Audit + Implementation for ${domain} is Being Prepared`
130            : `Order Confirmed — Your CRO Audit Report for ${domain} is Being Prepared`,
131        html,
132      });
133  
134      logger.success(`Confirmation email sent to ${email} (${result.id})`);
135      return { success: true, emailId: result.id };
136    } catch (error) {
137      logger.error(`Failed to send confirmation to ${email}`, error);
138      throw error;
139    }
140  }