47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
|
|
/**
|
|||
|
|
* Open-tracking pixel injector (Phase 4b). Appends a 1×1 transparent
|
|||
|
|
* image pointing at /api/public/email-pixel/[sendId] to outbound HTML
|
|||
|
|
* emails. The pixel endpoint records the open + cross-posts the event
|
|||
|
|
* to Umami.
|
|||
|
|
*
|
|||
|
|
* Sites that want to opt out of tracking simply don't call this helper.
|
|||
|
|
* The pixel URL is unguessable per-send (UUID), but a `track_opens=false`
|
|||
|
|
* row in `document_sends` makes the endpoint a no-op even if someone
|
|||
|
|
* does guess one.
|
|||
|
|
*
|
|||
|
|
* Privacy: respects EMAIL_REDIRECT_TO (no pixel injected when dev
|
|||
|
|
* redirect is active) so a re-routed message doesn't fire a fake open.
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
import { env } from '@/lib/env';
|
|||
|
|
|
|||
|
|
interface InjectOptions {
|
|||
|
|
/** Public base URL of the CRM (e.g. https://crm.portnimara.com).
|
|||
|
|
* Required so the pixel link is absolute — relative URLs break in
|
|||
|
|
* email clients. */
|
|||
|
|
appBaseUrl: string;
|
|||
|
|
/** UUID of the row in `document_sends`. */
|
|||
|
|
sendId: string;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Append a 1×1 tracking pixel just before `</body>` (or at the end of the
|
|||
|
|
* document if no `</body>` is present). Returns the HTML unchanged when
|
|||
|
|
* EMAIL_REDIRECT_TO is set so dev-mode re-routing doesn't generate
|
|||
|
|
* misleading open events.
|
|||
|
|
*/
|
|||
|
|
export function injectTrackingPixel(html: string, opts: InjectOptions): string {
|
|||
|
|
if (env.EMAIL_REDIRECT_TO) return html;
|
|||
|
|
|
|||
|
|
const base = opts.appBaseUrl.replace(/\/$/, '');
|
|||
|
|
const pixelUrl = `${base}/api/public/email-pixel/${opts.sendId}`;
|
|||
|
|
const pixelTag =
|
|||
|
|
`<img src="${pixelUrl}" width="1" height="1" alt="" ` +
|
|||
|
|
`style="display:block;border:0;margin:0;padding:0" />`;
|
|||
|
|
|
|||
|
|
if (html.includes('</body>')) {
|
|||
|
|
return html.replace('</body>', `${pixelTag}</body>`);
|
|||
|
|
}
|
|||
|
|
return html + pixelTag;
|
|||
|
|
}
|