|
| 1 | +# Impact.com Affiliate Tracking |
| 2 | + |
| 3 | +## Role of This Document |
| 4 | + |
| 5 | +This spec defines the business rules and invariants for affiliate conversion tracking via Impact.com for KiloClaw |
| 6 | +subscriptions. It is the source of truth for _what_ the system must guarantee — which events are tracked, how |
| 7 | +attribution is captured, what data is sent to Impact.com, and how the system behaves when tracking infrastructure is |
| 8 | +unavailable. It deliberately does not prescribe _how_ to implement those guarantees: handler names, column layouts, |
| 9 | +retry strategies, and other implementation choices belong in plan documents and code, not here. |
| 10 | + |
| 11 | +## Status |
| 12 | + |
| 13 | +Draft -- created 2026-03-31. |
| 14 | + |
| 15 | +## Conventions |
| 16 | + |
| 17 | +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", |
| 18 | +"NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC 2119] |
| 19 | +[RFC 8174] when, and only when, they appear in all capitals, as shown here. |
| 20 | + |
| 21 | +## Definitions |
| 22 | + |
| 23 | +- **Impact.com**: The third-party affiliate tracking platform used to attribute conversions to affiliate partners. |
| 24 | +- **UTT (Universal Tracking Tag)**: A JavaScript snippet provided by Impact.com that enables client-side tracking and |
| 25 | + cross-domain identity bridging. |
| 26 | +- **Click ID**: An opaque tracking identifier (`im_ref` query parameter) appended to landing page URLs by Impact.com |
| 27 | + when a visitor arrives via an affiliate tracking link. |
| 28 | +- **Conversion**: An event reported to Impact.com's Conversions API representing a meaningful step in the customer |
| 29 | + lifecycle (signup, trial, or subscription payment). |
| 30 | +- **Lead event**: A conversion representing a user signup. In Impact.com's parent-child model, this is the parent |
| 31 | + action. |
| 32 | +- **Sale event**: A conversion representing a trial or subscription payment. In Impact.com's parent-child model, these |
| 33 | + are child actions linked to the lead via the customer identifier. |
| 34 | +- **Affiliate attribution**: A record associating a user with the affiliate tracking identifier that brought them to |
| 35 | + the platform. |
| 36 | +- **First-touch attribution**: The attribution model used: only the first affiliate interaction per provider is recorded |
| 37 | + for a given user. |
| 38 | +- **Affiliate provider**: A named affiliate tracking platform (e.g. `impact`). The system supports multiple providers, |
| 39 | + each storing one attribution per user. |
| 40 | + |
| 41 | +## Overview |
| 42 | + |
| 43 | +Affiliate tracking enables Impact.com to attribute KiloClaw conversions to the affiliate partners that referred them. |
| 44 | +When a visitor arrives via an affiliate tracking link, the system captures and persists the tracking identifier. As the |
| 45 | +visitor progresses through the customer lifecycle — signup, trial, subscription — the system reports each stage to |
| 46 | +Impact.com as a conversion event, including the tracking identifier and customer details needed for attribution. |
| 47 | + |
| 48 | +The system uses a hybrid tracking architecture: a client-side JavaScript tag (UTT) for cross-domain identity bridging, |
| 49 | +and server-side API calls for reliable conversion reporting that is resistant to ad blockers and browser tracking |
| 50 | +prevention. |
| 51 | + |
| 52 | +This integration applies only to KiloClaw subscriptions. |
| 53 | + |
| 54 | +## Rules |
| 55 | + |
| 56 | +### Affiliate Attribution |
| 57 | + |
| 58 | +1. The system MUST support multiple affiliate providers, identified by a provider enum. The initial provider is |
| 59 | + `impact`. |
| 60 | + |
| 61 | +2. The system MUST store at most one attribution per user per provider. |
| 62 | + |
| 63 | +3. When a user arrives with an affiliate tracking identifier (`im_ref` query parameter for Impact.com), the system MUST |
| 64 | + persist the identifier before or during user creation. |
| 65 | + |
| 66 | +4. The system MUST preserve the tracking identifier across the authentication flow (e.g. through OAuth redirects) so it |
| 67 | + is available after the user is authenticated. |
| 68 | + |
| 69 | +5. Attribution MUST use first-touch semantics: if a user already has an attribution record for a given provider, |
| 70 | + subsequent tracking identifiers for that provider MUST NOT overwrite it. |
| 71 | + |
| 72 | +6. The tracking identifier MUST be treated as opaque. The system MUST NOT parse, validate the format of, or assign |
| 73 | + meaning to its contents. |
| 74 | + |
| 75 | +7. When a user record is deleted (e.g. GDPR soft-delete), the system MUST delete all affiliated attribution records for |
| 76 | + that user. |
| 77 | + |
| 78 | +### Conversion Events |
| 79 | + |
| 80 | +8. The system MUST report the following conversion events to Impact.com, in order of the customer lifecycle: |
| 81 | + |
| 82 | + | Event | Impact.com Type | Trigger | |
| 83 | + | ----------- | --------------- | --------------------------------------------- | |
| 84 | + | SIGNUP | Lead | New user creation (with attribution) | |
| 85 | + | TRIAL_START | Sale | KiloClaw trial subscription becomes active | |
| 86 | + | TRIAL_END | Sale | KiloClaw trial subscription ends (any reason) | |
| 87 | + | SALE | Sale | KiloClaw subscription invoice is paid | |
| 88 | + |
| 89 | +9. Each conversion event sent to Impact.com MUST include: |
| 90 | + - The user's affiliate tracking identifier (if available) |
| 91 | + - A stable customer identifier (the user's internal ID) |
| 92 | + - The customer's email address, SHA-1 hashed |
| 93 | + - An event timestamp |
| 94 | + - A unique order identifier (for sale events) |
| 95 | + |
| 96 | +10. SALE events MUST include the invoice amount and currency. |
| 97 | + |
| 98 | +11. SALE events MUST be reported for every paid KiloClaw invoice (initial purchase and renewals), not only the first. |
| 99 | + Impact.com determines commission eligibility based on its own contract rules. |
| 100 | + |
| 101 | +12. SALE events MUST include the subscription plan identifier (e.g. `kiloclaw-standard`, `kiloclaw-commit`) as the item |
| 102 | + category. |
| 103 | + |
| 104 | +13. Conversion events SHOULD include a promo code when one was applied to the transaction. |
| 105 | + |
| 106 | +14. The SIGNUP event MUST only be sent for new user creation, not for returning users who sign in. |
| 107 | + |
| 108 | +### Client-Side Tracking (UTT) |
| 109 | + |
| 110 | +15. The system MUST load the Impact.com UTT script on all pages when the UTT identifier is configured. |
| 111 | + |
| 112 | +16. The system MUST NOT load the UTT script when the UTT identifier is not configured. |
| 113 | + |
| 114 | +17. After a user authenticates, the system MUST call the UTT `identify` function with the user's internal ID and SHA-1 |
| 115 | + hashed email to enable cross-device attribution. |
| 116 | + |
| 117 | +### Reliability and Isolation |
| 118 | + |
| 119 | +18. Conversion reporting MUST NOT block or delay the primary operation it is attached to (user creation, subscription |
| 120 | + settlement, etc.). Failures in conversion reporting MUST be handled asynchronously. |
| 121 | + |
| 122 | +19. If Impact.com credentials are not configured, all tracking operations MUST be no-ops. The application MUST function |
| 123 | + normally without Impact.com configuration. |
| 124 | + |
| 125 | +20. The system SHOULD retry conversion API calls that receive a server error (5xx) response. |
| 126 | + |
| 127 | +21. The system MUST log conversion reporting failures for observability. |
| 128 | + |
| 129 | +### Rewardful Removal |
| 130 | + |
| 131 | +22. The existing Rewardful integration MUST be fully removed. This includes the client-side script, server-side cookie |
| 132 | + reading, and any checkout session metadata populated by Rewardful. |
| 133 | + |
| 134 | +### Checkout Metadata |
| 135 | + |
| 136 | +23. The KiloClaw checkout session MUST include the user's affiliate tracking identifier (if any) in Stripe subscription |
| 137 | + metadata, so it is available to webhook handlers independently of a database lookup. |
| 138 | + |
| 139 | +## Error Handling |
| 140 | + |
| 141 | +1. When a conversion API call fails with a client error (4xx), the system MUST log the error and MUST NOT retry. |
| 142 | + |
| 143 | +2. When a conversion API call fails with a server error (5xx), the system SHOULD retry with backoff. |
| 144 | + |
| 145 | +3. When a conversion API call fails for any reason, the primary operation (user creation, invoice settlement, etc.) MUST |
| 146 | + NOT be affected. |
| 147 | + |
| 148 | +4. When the affiliate tracking identifier is not available for a user (no attribution record exists), conversion events |
| 149 | + MUST still be sent with an empty or null click ID. Impact.com will not attribute these but may use them for |
| 150 | + reporting. |
| 151 | + |
| 152 | +## Changelog |
| 153 | + |
| 154 | +### 2026-03-31 -- Initial spec |
| 155 | + |
| 156 | +### 2026-03-31 -- Rename SUBSCRIPTION_START to SALE |
| 157 | + |
| 158 | +Renamed the SUBSCRIPTION_START event to SALE to reflect that it covers all KiloClaw payments (initial purchase and |
| 159 | +renewals), not just subscription creation. Clarified that SALE events fire for every paid invoice. |
0 commit comments