Skip to content

[CDX-470] Add additionalTrackingKeys option#472

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

[CDX-470] Add additionalTrackingKeys option#472
t3t3c wants to merge 13 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
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[bot]

This comment was marked as outdated.

@esezen esezen 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.

Thanks! This is looking great. I left some comments

Comment thread src/utils/request-queue.js
Comment thread spec/src/modules/tracker.js
Comment thread spec/src/modules/tracker.js
Comment thread src/constructorio.js Outdated
t3t3c and others added 2 commits July 3, 2026 12:46
- Use Set to remove duplicate additionalTrackingKeys and exclude the primary apiKey
- Assert duplicate request URL does not contain the original key
- Add test verifying request bodies are identical except for the key field
- Improve JSDoc description for additionalTrackingKeys parameter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-client-js

Resolve conflicts: keep both useWindowParameters (from master) and
additionalTrackingKeys (from this branch) in constructorio.js and
index.d.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
constructor-claude-bedrock[bot]

This comment was marked as outdated.

@evanyan13 evanyan13 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.

Hey @t3t3c
Thank you so much for making the changes! The PR is looking great in general. 🔥
Just left some comments for your consideration please

Comment thread src/constructorio.js
Comment thread src/utils/request-queue.js Outdated
Comment thread spec/src/utils/request-queue.js
Comment thread spec/src/utils/request-queue.js Outdated
Comment thread spec/src/modules/tracker.js
constructor-claude-bedrock[bot]

This comment was marked as outdated.

@evanyan13 evanyan13 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.

Hi @t3t3c
Thanks for making the changes so promptly!
Have left some comment regarding the new update to setClientOptions
For your consideration please

Comment thread src/constructorio.js
Comment thread src/constructorio.js
constructor-claude-bedrock[bot]

This comment was marked as outdated.

@evanyan13 evanyan13 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.

LGTM!
Thanks @t3t3c for the PR and the changes
@jjl014 Could we get your review & approval to push this change please
Thank you!

@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 an additionalTrackingKeys option that duplicates every tracking event to one or more additional API keys — the implementation is compact and the tests are thorough. A few correctness and reliability issues need to be addressed before merging.

Inline comments: 6 discussions added

Overall Assessment: ⚠️ Needs Work

expect(queue[2].url).to.contain('key=another-valid-key');
});

it('Should not duplicate events when additionalTrackingKeys contains the primary key or duplicates', () => {

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: This test is a good addition. However, the test verifies that queue.length === 2 (primary + one unique extra), which is correct. Consider also asserting that neither queue[0] nor queue[1] contains a duplicate of the primary key in both the URL and the body to make the intent of the deduplication explicit:

expect(queue[0].body.key).to.equal('primary-key');
expect(queue[1].body.key).to.equal('extra-key');

This guards against the body not being swapped even when the URL deduplication works correctly.

Comment thread spec/src/constructorio.js
additionalTrackingKeys: ['extra-key-1', 'extra-key-2'],
});

expect(instance.options).to.have.property('additionalTrackingKeys').to.deep.equal(['extra-key-1', 'extra-key-2']);

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: The setClientOptions test for additionalTrackingKeys only covers the DOM-less path. Given that the existing tests for other options (e.g. apiKey, segments) include a parallel test that asserts the change propagates to sub-module options (instance.tracker.options, instance.search.options, etc.), consider adding the same assertion here — or, at minimum, asserting instance.tracker.requests.options.additionalTrackingKeys if direct access is available. This ensures the shared-reference contract (noted above in the constructorio.js comment) is actually tested.

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.

Claude raised a good point. We should have equivalent tests for the DOM context.

@jjl014 jjl014 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.

Looking pretty solid to me. I did leave a couple comments that I'd like to get your thoughts on. Thanks!

Comment on lines +61 to +69
const encodedOriginalKey = helpers.encodeURIComponentRFC3986(this.options.apiKey);

const uniqueKeys = new Set(
additionalKeys.filter((key) => key && typeof key === 'string' && key !== this.options.apiKey),
);

uniqueKeys.forEach((additionalKey) => {
const encodedAdditionalKey = helpers.encodeURIComponentRFC3986(additionalKey);
const swappedUrl = url.replace(`key=${encodedOriginalKey}`, `key=${encodedAdditionalKey}`);

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.

Any reason why we're doing this validation and uniqueness check every time we queue an event?

It feels like an additional step that could be handled earlier (e.g. during client instantiation in the construtor or when setClientOptions is called)?

Comment thread spec/src/constructorio.js
additionalTrackingKeys: ['extra-key-1', 'extra-key-2'],
});

expect(instance.options).to.have.property('additionalTrackingKeys').to.deep.equal(['extra-key-1', 'extra-key-2']);

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.

Claude raised a good point. We should have equivalent tests for the DOM context.

Comment thread src/constructorio.js
this.options.serviceUrl = formattedServiceUrl || this.options.serviceUrl;
}

if (Array.isArray(additionalTrackingKeys)) {

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.

Not a big deal, but if we wanted to stop sending events to multiple keys, we would have to send [] at the moment. Should also support null here?

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.

5 participants