API Communication & Tracking
How the SDK fetches config and sends tracking events
Welcome back! In RuleManager, we saw how the SDK acts like a bouncer, checking if visitors meet specific criteria before they can participate in an experiment. We've covered how the SDK manages visitors, experiments, features, data, bucketing, and rules internally.
But how does the SDK get the initial setup information (like the details of your experiments and those rules) from Convert's servers? And how does it report back what happened (like which variation a visitor saw, or if they completed a goal)?
The Problem: Talking to the Outside World
Imagine the Convert SDK running in your application is like a local branch office. It needs to:
- Get Instructions: Receive the latest operational plan (your project configuration, including experiments, features, audiences) from the headquarters (Convert servers).
- Send Reports: Send status updates (tracking events like "visitor A saw variation B", "visitor C completed goal X") back to headquarters so you can see the results in your Convert dashboard.
How does this local branch office (the SDK) communicate reliably with headquarters (Convert servers)?
What is ApiManager? The SDK's Messenger
ApiManager? The SDK's MessengerMeet the ApiManager! Think of it as the dedicated messenger or communication link between the Convert SDK running in your application and the Convert backend servers.
Its primary jobs are:
- Fetching the Project Plan (
getConfig): When the SDK starts up (ConvertSDK / Core), if you provided ansdkKey, theApiManageris responsible for contacting the Convert servers and downloading the necessary project configuration data (all your experiments, features, rules, etc.). - Sending Tracking Reports (
enqueue,releaseQueue): When the SDK makes a decision (like assigning a visitor to a variation using the BucketingManager) or tracks a conversion, the DataManager tells theApiManagerabout it. TheApiManagerdoesn't send a separate message for every single event. Instead, it acts efficiently:- Collects Messages: It gathers these small tracking reports into a queue.
- Sends in Batches: It sends these collected reports back to the Convert tracking servers in batches. This is much more efficient than sending dozens of tiny messages individually.
In short, ApiManager handles all the "talking" the SDK needs to do with the external Convert platform.
How it's Used (Mostly Behind the Scenes)
Like several other managers (ExperienceManager, BucketingManager, RuleManager), you'll rarely interact directly with the ApiManager. It's mainly used internally by other core components:
-
By
Core: During initialization, theCoreclass uses theApiManager'sgetConfig()method to fetch the project configuration if ansdkKeywas provided.Conceptually, during configuration fetching, the Core calls the ApiManager's
getConfigmethod. If the call succeeds, the received data is processed and stored. If it fails, the error is handled appropriately. -
By
DataManager: When theDataManagerrecords a bucketing decision or a conversion event, it doesn't send it immediately. It tells theApiManagerto add the event to its queue usingenqueue().Conceptually, during bucketing retrieval, the DataManager first performs the bucketing logic to determine a chosen variation. It stores the decision locally via
putData. Then, if tracking is enabled, it creates an event data object and calls the ApiManager'senqueuemethod with the visitor ID and event data.
So, ApiManager is the behind-the-scenes worker handling the communication initiated by other parts of the SDK.
Under the Hood: How Communication Works
Let's look at the two main tasks: fetching data and sending tracking.
1. Fetching Configuration (getConfig)
- When
CorecallsapiManager.getConfig(), theApiManagerprepares and sends an HTTP GET request. - Target: It sends the request to the Convert configuration endpoint URL. The URL includes identifiers such as the
sdkKeyoraccountId/projectId(e.g.,https://cdn.convert.com/config/YOUR_SDK_KEYorhttps://cdn-4.convertexperiments.com/api/v1/config/{accountId}/{projectId}). - Response: The Convert server responds with a large JSON object containing all the details about your project (experiences, features, audiences, goals, etc.).
- Result: The
ApiManagerreceives this JSON data and passes it back to theCore, which then gives it to the DataManager for storage.
sequenceDiagram
participant Core as ConvertSDK / Core
participant ApiMgr as ApiManager
participant ConvertAPI as Convert Config API
Core->>+ApiMgr: getConfig()
Note over ApiMgr: Prepare HTTP GET request for config endpoint
ApiMgr->>+ConvertAPI: GET /config/{identifier}
ConvertAPI-->>-ApiMgr: Respond with Project JSON data
ApiMgr-->>-Core: Return Project JSON data
2. Sending Tracking Events (enqueue and releaseQueue)
This is a bit more complex because of the batching mechanism.
-
Step 1: Enqueue: When
DataManagercallsapiManager.enqueue(visitorId, eventData), theApiManagerdoesn't send anything yet. It simply adds theeventData(like a conversion or bucketing event) to an internal queue associated with thevisitorId. It also increments a counter for the queue length. -
Step 2: Check Batch Conditions: After adding the event,
ApiManagerchecks whether the queue size has reached thebatchSizelimit (default: 10 events). If so, it callsreleaseQueueimmediately. -
Step 3: Trigger Release: How the queue is released when the batch size is not reached depends on the platform (see Platform-Specific Differences below). The key point is that accumulated events will always be flushed eventually — either by a timer or at the end of the request lifecycle.
-
Step 4: Send Batch (
releaseQueue): WhenreleaseQueueis called:- It copies the current contents of the queue.
- It resets the internal queue so new events can be collected.
- It packages the copied events into a payload suitable for the Convert tracking API.
- It sends this payload as an HTTP POST request to the Convert tracking endpoint URL (like
https://track.convert.com/track/YOUR_SDK_KEY).
sequenceDiagram
participant DataMgr as DataManager
participant ApiMgr as ApiManager
participant ConvertAPI as Convert Track API
DataMgr->>+ApiMgr: enqueue(visitor1, event1)
Note over ApiMgr: Add event1 to queue. Queue size = 1.
DataMgr->>+ApiMgr: enqueue(visitor2, event2)
Note over ApiMgr: Add event2 to queue. Queue size = 2.
DataMgr->>+ApiMgr: enqueue(visitor1, event3)
Note over ApiMgr: Add event3 to visitor1's events. Queue size = 3.
loop When batch is full OR flush is triggered
ApiMgr->>ApiMgr: releaseQueue() triggered
Note over ApiMgr: Copy queue items. Reset queue.
Note over ApiMgr: Prepare HTTP POST payload with queued events.
ApiMgr->>+ConvertAPI: POST /track/{identifier} (payload)
ConvertAPI-->>-ApiMgr: Acknowledge receipt (e.g., HTTP 200 OK)
ApiMgr-->>ApiMgr: Handle response (log success/error)
end
This batching ensures the SDK doesn't overload the network with too many small requests, improving performance.
Key Implementation Details
1. Constructor / Initialization
The ApiManager is initialized with configuration that includes:
- API Endpoints: The config endpoint (for fetching project data) and the track endpoint (for sending events). Defaults are provided if not specified in configuration.
- Batch Settings: The
batchSize(default: 10) controls how many events accumulate before an automatic flush. - SDK Key / Project ID: Used to construct API paths.
- Tracking Toggle: Tracking can be disabled via configuration.
- Base Tracking Payload: A template structure containing the
accountId,projectId, and avisitorsarray that gets populated with queued events at flush time. - Internal Queue: An object or array that stores pending events, with methods to push new items and reset.
2. Fetching Configuration (getConfig)
The getConfig method constructs a path from the config endpoint base URL and the SDK key (or account/project identifiers), then performs an HTTP GET request. The JSON response data is extracted and returned to the caller.
3. Enqueuing Tracking Events (enqueue)
The enqueue method adds the event to the internal queue. It then checks if tracking is enabled and if the queue length has reached the batchSize. If the batch size is reached, releaseQueue is called immediately. Otherwise, the platform-specific flush mechanism handles it (timer or shutdown handler).
4. Releasing the Queue (releaseQueue)
The releaseQueue method:
- Returns early if the queue is empty or tracking is disabled.
- Copies the current queue items into a tracking payload that includes the base tracking information (account ID, project ID) plus the visitor events.
- Resets the queue before sending, so new events arriving during the network request are added to a fresh queue.
- Sends the payload as an HTTP POST to the tracking endpoint.
- Handles errors by logging them. On success, a system event may be fired to notify other components.
Platform-Specific Differences
| Aspect | Browser / Node.js (JS SDK) | Server-side (PHP SDK) |
|---|---|---|
| Queue flush trigger (non-full batch) | A timer (setTimeout) starts when the first event is enqueued. If the release interval (default: 10 seconds) elapses before the batch fills, the queue is flushed automatically. | No timers. A shutdown handler (register_shutdown_function) flushes all remaining events when the request ends. Under PHP-FPM, fastcgi_finish_request() sends the HTTP response to the client first, so flushing adds no user-visible latency. |
| Release interval | Configurable (default: 10,000 ms). The timer is started/stopped as events are enqueued and flushed. | Not applicable. Events accumulate during a single request and are sent in one batch at the very end. |
| HTTP client | Built-in HttpClient utility (uses fetch, XMLHttpRequest, or equivalent). In browsers, may use navigator.sendBeacon() for reliability when the user navigates away. | PSR-18 compatible HTTP client, auto-discovered via php-http/discovery or provided via dependency injection. |
| Retry logic | Basic error handling with logging. Retry/backoff logic is a potential future enhancement. | Automatic retries on 5xx/network errors: up to 2 retries with backoff delays of 100ms and 300ms. Does NOT retry on 4xx client errors. |
| Timer management | startQueue() and stopQueue() methods manage the release interval timer. | No timer management methods — unnecessary in a request-scoped execution model. |
Conclusion
The ApiManager is the vital communication link between the Convert SDK operating in the user's environment and the Convert backend servers. It acts as the messenger, responsible for:
- Fetching the project configuration (
getConfig) when the SDK initializes (if using ansdkKey). - Collecting and Batching tracking events (
enqueue). - Sending these batched events (
releaseQueue) efficiently back to Convert for reporting.
While you don't usually call its methods directly, understanding the ApiManager helps clarify how the SDK gets its instructions and reports results back to your Convert dashboard. It relies on batching and platform-appropriate flush mechanisms to do this efficiently.
We've now seen how most of the core managers interact and rely on each other. But how do these components signal to each other when something important happens, like when the configuration data has been successfully fetched and the SDK is ready? For internal communication, the SDK uses an event system.
Let's explore this internal notification system next: EventManager!
Updated 29 days ago