Skip to content

[CDX-470] Add additionalTrackingKeys option#472

Open
t3t3c wants to merge 4 commits into
masterfrom
cdx-470-add-additionaltrackingkeys-option-to-client-js
Open

[CDX-470] Add additionalTrackingKeys option#472
t3t3c wants to merge 4 commits into
masterfrom
cdx-470-add-additionaltrackingkeys-option-to-client-js

Conversation

@t3t3c

@t3t3c t3t3c commented Jun 22, 2026

Copy link
Copy Markdown

Summary

  • Adds additionalTrackingKeys option to ConstructorClientOptions that accepts an array of API key strings
  • When configured, every tracking event queued via RequestQueue is duplicated for each additional key, with the key swapped in both the URL query string and POST body
  • Invalid entries (non-strings, empty strings) are filtered out silently

Usage

const cio = new ConstructorIO({
  apiKey: 'primary-key',
  sendTrackingEvents: true,
  additionalTrackingKeys: ['secondary-key', 'tertiary-key'],
});

// All tracker methods now send events to all 3 keys
cio.tracker.trackPurchase({ items: [...], revenue: 12.00 });

Changes

  • src/types/index.d.ts — Added additionalTrackingKeys?: string[] to options interface
  • src/constructorio.js — Pass through the new option
  • src/utils/request-queue.js — Duplicate queued requests for each additional key
  • spec/src/utils/request-queue.js — Unit tests (5 cases)
  • spec/src/modules/tracker.js — Integration test

Test plan

  • Unit tests: duplication works, empty array, missing option, invalid entries, GET requests
  • Integration test: fetch called with both primary and additional key URLs
  • Existing test suite: no regressions
  • Lint passes

Resolves CDX-470

…vents

Adds a new `additionalTrackingKeys` client option that duplicates tracking
events to additional API keys. When configured, each tracking event queued
via RequestQueue is also sent to each additional key with the `key` parameter
swapped in both the URL and POST body.
Copilot AI review requested due to automatic review settings June 22, 2026 10:28
@t3t3c t3t3c requested a review from a team as a code owner June 22, 2026 10:28
constructor-claude-bedrock[bot]

This comment was marked as outdated.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an additionalTrackingKeys client option to support duplicating tracking events across multiple Constructor.io API keys, primarily by cloning queued RequestQueue entries with the key swapped in the URL/body.

Changes:

  • Introduces additionalTrackingKeys?: string[] on ConstructorClientOptions and wires it through ConstructorIO options.
  • Updates RequestQueue to enqueue duplicate tracking requests per additional key.
  • Adds unit + integration tests validating duplication behavior and invalid-key filtering.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/utils/request-queue.js Duplicates queued tracking requests for each configured additional key
src/types/index.d.ts Adds additionalTrackingKeys?: string[] to the public options type
src/constructorio.js Plumbs additionalTrackingKeys through normalized client options
spec/src/utils/request-queue.js Unit tests for duplication, empty/missing option, invalid entries, GET behavior
spec/src/modules/tracker.js Integration test asserting fetch is called for both primary + additional keys

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/utils/request-queue.js Outdated
Comment thread src/constructorio.js
Comment on lines +96 to 97
additionalTrackingKeys,
} = options;
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
constructor-claude-bedrock[bot]

This comment was marked as outdated.

@constructor-claude-bedrock constructor-claude-bedrock Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR adds additionalTrackingKeys to fan out tracking events to multiple API keys by duplicating queue entries in RequestQueue. The implementation is mostly sound but has a correctness bug with URL replacement, a test isolation gap, and a few reliability concerns worth addressing.

Inline comments: 6 discussions added

Overall Assessment: ⚠️ Needs Work

additionalTrackingKeys: [],
});

requests.queue('https://ac.cnstrc.com/behavior?action=session_start&key=primary-key&_dt=123');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important Issue: The GET test ('Should add duplicate requests for GET method') asserts queue[1].body.key equals 'extra-key-1', but the primary request was queued with no explicit body argument (defaults to {}). The assertion passes only because the duplicated entry spreads {} and then sets key. However, this conflates the GET-path body handling with POST semantics. The test should also assert queue[0].body to be {} (or undefined) to document the intended contract for GET requests, making the asymmetry visible and intentional.

callCount += 1;

if (callCount === 2) {
expect(fetchSpy).to.have.been.calledTwice;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important Issue: The integration test relies on fetchSpy.getCall(0) and getCall(1) being the two calls from this test. But fetchSpy is a module-level variable re-assigned in each beforeEach — it is not reset between describe blocks. If a prior test in the suite has already recorded calls on the spy, getCall(0) and getCall(1) may refer to the wrong invocations.

Use fetchSpy.args relative to the current test context, or (preferred) create a dedicated spy scoped to this test:

const localSpy = sinon.spy(fetch);
const { tracker } = new ConstructorIO({
  apiKey: testApiKey,
  fetch: localSpy,
  ...
});
// then assert localSpy.getCall(0) / localSpy.getCall(1)

Also, calledTwice is asserted inside a callback that fires only once (when callCount === 2). If the first call triggers an error and second triggers success (or vice versa), getCall(0).args[0] may be the secondary-key request, not the primary. Asserting on url.includes for both keys (without assuming order) would make this more robust.

Comment thread src/constructorio.js
beaconMode,
networkParameters,
humanityCheckLocation,
additionalTrackingKeys,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: additionalTrackingKeys is passed through to this.options as-is without any normalisation (no filtering of non-strings, no deduplication). The filtering is deferred to RequestQueue.queue(). This is a valid design choice, but consider documenting it or — better — normalising in ConstructorIO constructor so that this.options.additionalTrackingKeys always contains only valid, deduplicated strings. This prevents surprises if other code paths ever read the option directly without going through RequestQueue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants