record_conversion
Record a post-scan conversion event (purchase, signup) to track ROI for a QR code. Include event name, optional value, and metadata.
Instructions
Record a post-scan conversion event (purchase, signup, etc.) for a QR code you own. Use this to track ROI — e.g., when a user scans a QR code and then makes a purchase, record a 'purchase' conversion with the order value. For client-side tracking without code, use the tracking pixel: .
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| short_id | Yes | The short_id of the QR code this conversion is for. | |
| event | Yes | The conversion event name (e.g., "purchase", "signup", "add_to_cart"). Use consistent names to aggregate stats. | |
| value | No | Optional monetary value of the conversion (e.g., 49.99). | |
| metadata | No | Optional JSON metadata (e.g., product ID, order number). |
Implementation Reference
- Core service function that inserts a conversion event into the database and returns the created record.
export function recordConversion(input: { qrCodeId: number; eventName: string; value?: number | null; metadata?: Record<string, unknown> | null; referer?: string | null; ip?: string | null; }) { const inserted = db .insert(conversionEvents) .values({ qrCodeId: input.qrCodeId, eventName: input.eventName, value: input.value != null ? String(input.value) : null, metadata: input.metadata ? JSON.stringify(input.metadata) : null, referer: input.referer ?? null, ip: input.ip ?? null, }) .returning() .get(); return { id: inserted.id, event: inserted.eventName, value: inserted.value ? parseFloat(inserted.value) : null, metadata: inserted.metadata ? JSON.parse(inserted.metadata) : null, created_at: inserted.createdAt, }; } - Fastify schema for the POST /api/conversions endpoint, defining request body and 201 response shape.
export const conversionRecordSchema = { body: { type: "object" as const, required: ["short_id", "event"], properties: { short_id: { type: "string", description: "The short_id of the QR code this conversion is for.", }, event: { type: "string", maxLength: 100, description: 'The conversion event name (e.g., "purchase", "signup", "add_to_cart"). Use consistent names to aggregate stats.', }, value: { type: "number", description: "Optional monetary value of the conversion (e.g., 49.99).", }, metadata: { type: "object", additionalProperties: true, description: "Optional JSON metadata for the conversion (e.g., product ID, order number).", }, }, }, response: { 201: { type: "object", properties: { id: { type: "integer", description: "Conversion event ID." }, short_id: { type: "string" }, event: { type: "string" }, value: { type: "number", nullable: true }, metadata: { type: "object", nullable: true, additionalProperties: true }, created_at: { type: "string" }, }, }, }, };