diff --git a/event/event.go b/event/event.go index 3e28966..da4e6a2 100644 --- a/event/event.go +++ b/event/event.go @@ -108,6 +108,20 @@ const ( // 5 hand-written `pevent.Type("track.purchase")` literals with this // typed constant. TrackPurchase Type = "track.purchase" + // ServerPurchase — the server-side confirmed-order fallback for + // track.purchase (wishlist dual-channel style, W6d pattern). Emitted by + // the order service's durable outbox when an order reaches StatusCaptured + // (the same atomic emitOnApply that publishes order.created), so a + // purchase is recorded even when the browser beacon was blocked (no JS / + // no consent). Deliberately session-less: it carries catalog item ids + // only — no session id, no customer identity (C5) — and feeds the + // session-less co-occurrence AlsoBought intra-pair on the tracking side. + // It must NOT ride the browser `track.purchase` type: the consumer + // routes that through the session-keyed HandlePurchaseEvent (funnel + + // converted label), which a session-less event would corrupt. Wire + // routing key `track.purchase_server` rides the existing `track.*` + // binding on the catalog exchange. Payload is an event.ServerPurchaseEvent. + ServerPurchase Type = "track.purchase_server" // TrackPromotionView / TrackPromotionClick — storefront promotion // attribution. Producer: the storefront promotion-badge islands, PLP // promo badges, bundle picker and cart bundle upsell (lib/track.ts @@ -215,6 +229,32 @@ type WishlistMutationEvent struct { ItemId uint32 `json:"itemId,omitempty"` } +// PurchaseItem is one line of a confirmed order in a ServerPurchaseEvent. +// ItemId is the numeric catalog (finder) item id the tracking pipeline keys +// on; lines without one (added without catalog facts) are skipped by the +// producer. Quantity mirrors the order line quantity. +type PurchaseItem struct { + Sku string `json:"sku,omitempty"` + ItemId uint32 `json:"itemId"` + Quantity uint `json:"quantity,omitempty"` +} + +// ServerPurchaseEvent is the payload for track.purchase_server (the order +// service's confirmed-order fallback). Deliberately pseudonymous (C5): order +// id + catalog item ids + optional session id only — never the customer +// email/name/profile id, so the tracking pipeline can pair "these items were +// bought together" without being able to attribute the purchase to a person. +// SessionId is the tracking session (sid) captured at checkout start and +// threaded through the checkout→order handoff; when > 0 the tracking +// consumer routes the purchase through the session-keyed path (funnel + +// converted label), when 0 it stays session-less (no consent / server-side +// checkout). +type ServerPurchaseEvent struct { + OrderID string `json:"orderId"` + SessionId int64 `json:"session_id,omitempty"` + Items []PurchaseItem `json:"items"` +} + // CartToWishlistEvent is the payload for cart.to_wishlist (cart service). // Carries the pseudonymised owner profile id (the cart's UserId — a // customer-scoped opaque uint64 id, never an email/name) plus the list the