# AnyTrack: Pass the AnyTrack Click ID to Stripe We at AnyTrack provide this prompt to help you pass the **AnyTrack Click ID** (`atclid`) into Stripe. Inspect this website and implement the required changes using its existing framework, backend, Stripe integration, and purchase types. Cover every active checkout path you find, while retaining correct existing attribution code. Use the name “AnyTrack Click ID” throughout your implementation notes and customer-facing explanations. **Strict scope: do not change the architecture or modify any existing flow. The final result must behave exactly as it does today, with the only functional addition being retrieval of the AnyTrack Click ID generated by our Tracking Tag and passing it to Stripe through the existing integration. Additional changes or fixes are out of scope.** Make only the minimal attribution-specific changes needed in existing code paths and payloads. The only permitted timing change is awaiting the bounded async `atclid` lookup described below before the existing checkout creation request. Do not refactor, redesign, migrate integrations, upgrade dependencies, add checkout steps, or otherwise change UI, business logic, payment behavior, request sequencing, or payment retry behavior. Do not fix unrelated issues you discover. If attribution cannot be added within these constraints, report the specific limitation instead of changing the architecture or flow. Do not deploy or publish the changes to the live site: the customer reviews and tests them first. These constraints apply to every instruction below. The customer may use a Stripe server SDK or make direct HTTP requests to the Stripe API. Both approaches are supported. Keep whichever approach the customer already uses; do not replace SDK calls with direct API requests or introduce an SDK where direct requests already work. The intended flow in either case is: `Async AnyTrack('atclid') lookup in the browser → existing checkout/payment request's atclid field → backend → Stripe metadata.atclid (value unchanged)` Implement when code access is available; otherwise provide concrete instructions for the detected integration. Ask only for information you cannot establish from the project and that is necessary to proceed. ## 1. Discover the integration before editing First, verify that the customer's AnyTrack Tracking Tag is installed on the relevant website pages. **If the tag is missing, stop the task and tell the customer: “The AnyTrack Tracking Tag is not installed. Please install it on your website and confirm when it is installed so I can continue.” Do not continue implementation until the customer explicitly confirms installation.** After confirmation, re-check the installation before proceeding; if it is still missing, report that and remain stopped. Do not install the tag yourself, request a snippet as a substitute for confirmation, copy another site's tag, or invent a property ID. This is an implementation prerequisite. Once the tag is installed, temporary runtime unavailability is handled by the bounded lookup below; an unavailable `window.AnyTrack` during page loading alone does not establish that the installation is missing. Trace each checkout entry point to the code or platform that creates the Stripe object. Inspect the frontend, request schemas, backend routes or server actions, Stripe calls, installed SDK versions, configured API version, and any existing attribution mapping. Do not print secret values. For projects built with Lovable, Base44, or similar platforms, identify the existing checkout implementation and platform-native backend functions or payment integration. Inspect the actual project; do not assume a particular backend or Stripe flow from the platform name. Pass the browser-retrieved AnyTrack Click ID through that existing mechanism and attach it where the Stripe object is created, using the matching metadata fields in section 4. Preserve platform SDK calls, function invocation, authentication, secrets management, and checkout behavior. If a managed integration does not expose the required per-checkout metadata fields, report the specific limitation; do not replace the integration or introduce a new backend. Identify: - Whether the backend uses a Stripe server SDK, direct HTTP API requests, or both, and where each Stripe object is created. - How checkout data reaches the backend: JSON, FormData/multipart, URL-encoded or native form submission, framework server actions, or another existing transport. Identify its parser and validation schema as well. - Hosted Checkout, embedded Checkout, custom Checkout using the Checkout Sessions API, direct PaymentIntents, or direct Billing Subscriptions. - One-time purchases, subscriptions, mixed carts, trials, and delayed or off-session charges actually supported by the site. Use Stripe's mode and recurring price configuration as evidence; product names such as “monthly supply” are insufficient. - Where the AnyTrack Tracking Tag loads, which property it belongs to, and whether existing code already collects and passes the AnyTrack Click ID. - When Stripe objects are created relative to the checkout action, including objects created on page load or after a queued backend job. A Payment Element alone does not identify the backend flow. Trace whether its client secret comes from a Checkout Session, a direct PaymentIntent, or a Subscription's invoice payment. Briefly list the detected flows and evidence, then implement the applicable branches. Keep the existing SDK/API version and UI mode values; this task does not require an integration migration. ## 2. Retrieve the AnyTrack Click ID in the browser Use the customer's installed AnyTrack Tracking Tag after the prerequisite in section 1 is satisfied. Avoid duplicate AnyTrack Tracking Tag installations. Don't create new utilities for getting the AnyTrack Click ID, but rely on the below helper `getAnyTrackClickId`. Don't generate it yourself by directly calling `AnyTrack('atclid')` or substitute a random UUID, email, Stripe customer ID, `gclid`, or `fbclid`. Use the helper `getAnyTrackClickId` to get the AnyTrack Click ID. The helper `getAnyTrackClickId` is an async function, it tries to get the AnyTrack Click ID and retries every 300ms during 5 seconds before giving up. In worst case the helper will return undefined, which is safe to send to the API later. Call this helper only in the browser checkout handler, using `await getAnyTrackClickId()` where appropriate. When a new checkout/purchase flow attempt begins, the call of `getAnyTrackClickId` function will get the AnyTrack Click ID to include it into the request that eventually sends the value to Stripe (as instructed in the later section). ```js async function getAnyTrackClickId(browser = globalThis) { const deadline = performance.now() + 5000; while (performance.now() < deadline) { try { const AnyTrack = browser?.AnyTrack; if (typeof AnyTrack === 'function') { const atclid = AnyTrack('atclid'); if (typeof atclid === 'string' && atclid.length > 0) return atclid; } } catch { // The tracker may become available on a later attempt. } const remaining = deadline - performance.now(); if (remaining <= 0) break; await new Promise((resolve) => setTimeout(resolve, Math.min(300, remaining))); } console.error('[AnyTrack] Could not retrieve the AnyTrack Click ID within 5 seconds.'); return undefined; } ``` Retain the lookup promise and its result per checkout attempt using the existing browser submission handler or attempt context; do not require a particular frontend framework or state model. Keep the existing idempotency key and access token associated with the attempt, if used. Reuse the same promise/result for the same attempt, including a final `undefined`; a payment/API retry must not restart the 5-second lookup. Preserve the existing busy/submission guard so repeated clicks cannot create parallel checkouts. If an attempt is canceled or replaced while waiting, its result must not submit a stale checkout. Start a new lookup only for a genuinely new attempt. Do not add persistence or a new payment retry system. If the customer already carries checkout context across steps or queued jobs, pass the field through that existing context. ## 3. Carry attribution through the existing backend boundary Preserve the customer's existing browser-to-backend transport, content type, endpoint or server action, parser, and submission behavior. Do not convert forms or server actions to JSON/fetch, introduce a new API endpoint, or replace the transport to add attribution. Always name the field or argument carrying the AnyTrack Click ID `atclid` throughout the existing checkout context, payloads, schemas, and backend mappings. If an existing attribution field uses another name, update that field and its mappings consistently to `atclid` within the existing transport. The final Stripe metadata key must also be exactly `atclid`. After awaiting the lookup, pass the resolved string unchanged using the existing format. On timeout, `undefined` is returned. Do not serialize it as an empty string, `null`, or the string `"undefined"`: | Existing browser-to-backend transport | On successful lookup | On timeout | | --- | --- | --- | | JSON | Include `atclid` in the existing payload. | Omit the property; `JSON.stringify` also omits object properties whose value is `undefined`. | | FormData/multipart or URLSearchParams | Set the `atclid` field to the resolved string using the existing serializer. | Omit/delete the attribution field; do not pass `undefined` to `.set()` or `.append()`, which would stringify it. | | Native HTML form | Populate a hidden input named `atclid` before the existing submission. | Remove or disable that attribution input so it is not submitted. | | Framework server action or other transport | Pass `atclid` through the existing action's supported argument or form payload. | Use its supported optional-field representation, without inventing a placeholder value. | For form submissions, integrate the bounded lookup into the existing submit handling while preserving validation, the submitter's name/value and action, CSRF fields, redirects, and duplicate-submission protection. Ensure serialization round-trips the exact AnyTrack Click ID; transport encoding is not sanitization. Read the field on the server through the existing parser or action argument rather than assuming a JSON body. Hosted, embedded, and custom Checkout send the field through the customer's existing Checkout Session creation request; direct one-time checkout uses the existing PaymentIntent creation request; direct subscription checkout uses the existing Subscription creation request. Route names such as `/api/checkout-sessions`, `/api/payment-intents`, and `/api/subscriptions` are examples, not names to impose on the project. In all eight cases the browser sends the AnyTrack Click ID to the application's backend, and the backend sends it to Stripe. Update every intervening schema, validator, action, service, and queued payload that could drop this field. For delayed creation, retain the browser-captured value with the specific order or checkout context until the backend creates the Stripe object. On the server, pass the supplied AnyTrack Click ID through unchanged. Check only that it is a non-empty string before adding metadata. Do not sanitize, trim, truncate, remove control characters, hash, or otherwise rewrite it: ```js function createAtclidMetadata(atclid) { return typeof atclid === 'string' && atclid.length > 0 ? { atclid } : {}; } ``` Adapt the same behavior to the backend's language. The value retrieved from AnyTrack must be identical to the value sent in Stripe metadata. Missing attribution must not prevent checkout or send an empty `metadata.atclid` value that could clear an existing value. Pass the extracted `atclid` field or argument to `createAtclidMetadata` (or its equivalent in the backend's language), then merge the result into the relevant existing metadata maps without replacing other keys or nested payment/subscription settings. Extraction may use a parsed body field such as `body.atclid`, `formData.get('atclid')`, or an `atclid` server-action argument, depending on the existing integration. Attach this metadata during Stripe object creation without a separate attribution update request. If a customer's existing flow pre-creates an object, use an existing server-side update path for the correctly owned object only if it can carry the field without changing the flow. Otherwise report the limitation. Do not move object creation, add requests or checkout steps, or reorder confirmation to accommodate attribution. Keep secret-key Stripe requests on the backend. Do not add arbitrary metadata to Stripe.js confirmation arguments, billing details, Payment Element options, or a hosted Checkout URL. Use metadata for the AnyTrack Click ID and preserve any existing business use of `client_reference_id`. Preserve server-owned prices, authentication, object ownership, idempotency, capture behavior, subscription settings, and redirect handling. ## 4. Apply the matching Stripe API branch The table lists fields to supply through the existing Stripe server SDK call or direct HTTP API request. The metadata destinations are the same in both cases; adapt the parameter syntax and serialization to the customer's SDK/language or HTTP client. “Stripe request” in this prompt includes either approach. Implement only the rows the project uses, but cover all discovered entry points for those rows. | Detected integration | Purchase type | Fields to populate with the unchanged AnyTrack Click ID | | --- | --- | --- | | Hosted Checkout Session | One-time | `metadata.atclid` and `payment_intent_data.metadata.atclid` | | Hosted Checkout Session | Subscription | `metadata.atclid` and `subscription_data.metadata.atclid` | | Embedded Checkout Session | One-time | `metadata.atclid` and `payment_intent_data.metadata.atclid` | | Embedded Checkout Session | Subscription | `metadata.atclid` and `subscription_data.metadata.atclid` | | Custom Checkout using Sessions | One-time | `metadata.atclid` and `payment_intent_data.metadata.atclid` | | Custom Checkout using Sessions | Subscription | `metadata.atclid` and `subscription_data.metadata.atclid` | | Direct PaymentIntent, including Elements | One-time | PaymentIntent `metadata.atclid` | | Direct Billing Subscription, including Elements for its invoice payment | Subscription | Subscription `metadata.atclid` | For Sessions, branch on the actual `mode`: use `payment_intent_data` for `payment` and `subscription_data` for `subscription`. A mixed cart handled in subscription mode follows the subscription branch. Keep Session metadata as well as the underlying object's metadata. See [Checkout Session creation](https://docs.stripe.com/api/checkout/sessions/create), [PaymentIntent creation](https://docs.stripe.com/api/payment_intents/create), and [Subscription creation](https://docs.stripe.com/api/subscriptions/create). For subscriptions, attach the AnyTrack Click ID to the Subscription at creation. Renewals do not require a new browser lookup or attribution request. Do not add separate writes of `atclid` to invoice metadata or the subscription's invoice PaymentIntent, invoice updates, renewal hooks, or webhook handlers. If inspecting an existing downstream consumer, distinguish Stripe's own metadata propagation from writes performed by the application; see [Stripe's metadata propagation rules](https://docs.stripe.com/metadata#copy-metadata-to-another-object). Do not use Customer metadata alone as the transaction attribution source or overwrite historical subscription attribution on every visit. For SetupIntents, setup-mode Sessions, invoice-only flows, subscription schedules, or legacy Charge integrations, trace the eventual payment-producing object and check its version-specific API. Saving a payment method is not a purchase; preserve the AnyTrack Click ID through the application's existing context and attach it when the actual payment or subscription is created. Don't create a new webhook, or change if any webhooks exist. The current task is only about passing the AnyTrack Click ID to Stripe. ## 5. Verify each detected path and report the result Use focused automated checks and Stripe test mode or sandbox where available. Never create live charges to verify tracking. Cover: - The AnyTrack Tracking Tag installation prerequisite is satisfied. If installation is missing, stop and wait for the customer's explicit confirmation before continuing implementation. - A retrieved string is named `atclid` throughout the existing checkout context and backend boundary and passes unchanged to every required Stripe `metadata.atclid` field. - The existing browser-to-backend transport and parser are preserved. Verify successful field extraction and omission on timeout using the actual JSON, form, server-action, or other supported payload; no placeholder string is sent. - Each active UI/purchase combination, including any pre-created objects, deferred creation, trials, or retry paths the site actually supports. - Lookup attempts run immediately and then every 300 ms until success or the 5-second deadline. Missing or throwing AnyTrack, bootstrap queue return values, and empty results are retried. Replacing the bootstrap function with the loaded SDK during polling works. - Success resolves the exact AnyTrack Click ID and stops polling. Timeout logs one error without the raw AnyTrack Click ID, resolves `undefined`, and lets checkout proceed with the optional attribution field omitted and no added `atclid` metadata. No timer continues polling after completion. - A missing AnyTrack Click ID does not erase existing Stripe metadata. Payment/API retries reuse the original attempt's lookup promise/result, including `undefined`, and do not create another polling window. Separate checkout attempts keep their own state. - Existing submission guards prevent duplicate requests while awaiting the lookup, and canceled or replaced attempts cannot submit after their lookup resolves. - The architecture and existing flows remain unchanged apart from the explicitly requested bounded lookup before checkout creation. Review the diff to confirm every production-code change is strictly necessary to retrieve or pass `atclid`, with no unrelated changes or fixes. When test/sandbox credentials and access permit, complete a sandbox checkout and inspect the resulting Stripe objects server-side or in the Dashboard. Distinguish source inspection, mocked requests, actual Stripe object verification, and confirmed AnyTrack ingestion; report only what you verified. Finish with a compact table of detected flows, changed files or platform settings, destination fields, verification results, and any remaining customer action. If all relevant paths are already correct, verify and report that rather than rewriting them. The scope is carrying the AnyTrack Click ID into Stripe. Preserve existing analytics events; do not add duplicate `InitiateCheckout`/`Purchase` events or a new webhook pipeline as a side effect. After the setup is ready to generate atclid and pass it to Stripe as a metadata field, and the project's flows are covered, with this, tell at the end: ✔️Finished successfully