On-pack code entry
The full recipe for a code-entry promotion: the shopper types the unique code from the pack with their details, Loranj burns the code and saves the entry.
Validate as they type
const check = promo.validate(input);
// { ok: true } or { ok: false, errors: { email: "Enter a valid email address" } }
Custom fields are keyed as answers.<key> in errors. Validation here is a convenience; Loranj validates again on the server.
Submit and handle every result
const result = await promo.submitEntry(input, { turnstileToken });
switch (result.status) {
case "accepted": // result.entryId: show success
case "invalid": // result.errors by field: show inline errors
case "invalid_code": // the code doesn't exist for this campaign
case "code_used": // someone has already used this code
case "entry_limit_reached": // this person has entered the maximum times
case "closed": // after the end date
case "not_started": // before the start date
case "bot_check_failed": // reset the Turnstile widget and try again
case "rate_limited": // wait result.retryAfter seconds
}
Retries are safe
Each submission carries an idempotency key. The SDK retries network and server errors with the same key, and reuses it if the shopper presses "Try again". A code is never redeemed twice, and the shopper never sees "code used" for their own entry. Double clicks send one request.
Codes
Codes are generated in batches in the dashboard and downloaded once for printing. Loranj stores only a keyed hash, so they can't be read back. Input is normalised (case, spaces and dashes), and codes avoid lookalike characters.