Skip to content

feat: braze ecommerce events onboarding#3076

Open
ItsSudip wants to merge 8 commits into
developfrom
feature/int-4303-braze-update-with-recommended-events-in-web-device-mode
Open

feat: braze ecommerce events onboarding#3076
ItsSudip wants to merge 8 commits into
developfrom
feature/int-4303-braze-update-with-recommended-events-in-web-device-mode

Conversation

@ItsSudip

@ItsSudip ItsSudip commented Jun 21, 2026

Copy link
Copy Markdown
Member

PR Description

Adds support for Braze's recommended ecommerce events in the web device mode integration, mirroring the cloud-mode mapping. Gated behind a new opt-in config flag useRecommendedEcommerceEvents (default off); when off, the existing legacy custom-event / logPurchase path is unchanged.

When enabled, mapped RudderStack ecommerce events are emitted via globalThis.braze.logCustomEvent(name, properties) (including Order Completed, which maps to ecommerce.order_placed rather than logPurchase).

Event mapping (RS → Braze):

RudderStack event Braze event Notes
Product Viewed ecommerce.product_viewed flat, no products[]
Product Added ecommerce.cart_updated action: 'add', single-product wrap
Product Removed ecommerce.cart_updated action: 'remove'
Checkout Started ecommerce.checkout_started
Order Completed ecommerce.order_placed
Order Refunded ecommerce.order_refunded
Order Cancelled ecommerce.order_cancelled

Cart Viewed / Cart Updated are intentionally unmapped and fall through to the legacy path.

Changes:

  • ecommerceUtil.js (new) — event-name resolution, per-event + per-product field mappings, products[] construction, unmapped-key → metadata pass-through, and source derivation ('web', with valid properties.source taking precedence).
  • browser.js — reads the useRecommendedEcommerceEvents flag and routes mapped events through the new builder.
  • Validation posture matches cloud's "send-anyway": on missing Braze-required fields, emit a single logger.warn and still call logCustomEvent.
  • Empty products[] and other empty/null fields are stripped from the payload before sending (the missing-field warning still fires).

Linear task

INT-4303

Cross Browser Tests

Please confirm you have tested for the following browsers:

  • Chrome
  • Firefox
  • IE11

Sanity Suite

  • All sanity suite test cases pass locally

Security

  • The code changed/added as part of this pull request won't create any security issues with how the software is being used.

Summary by CodeRabbit

  • New Features
    • Added support for Braze recommended ecommerce events. When enabled, ecommerce events are routed to Braze’s dedicated ecommerce endpoints with correctly normalized sources, mapped fields, and products payload shaping.
  • Bug Fixes
    • Improved cart, checkout, and order handling, including correct precedence for “order completed,” consistent action derivation, and scrubbing of null/empty product and metadata values.
    • Missing or empty required ecommerce data now triggers warnings while still sending the event; unmapped events use the legacy tracking path.
  • Tests
    • Added comprehensive Jest coverage for event mapping, payload transformations, and edge cases.
  • Chores
    • Updated the legacy CDN bundle size limit.

Copilot AI review requested due to automatic review settings June 21, 2026 12:51
@ItsSudip ItsSudip requested a review from a team as a code owner June 21, 2026 12:51
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

A new ecommerceUtil.js module defines RS-to-Braze event mappings, per-event field specifications, and payload builders that transform RudderStack ecommerce events into Braze ecommerce endpoints. browser.js imports these utilities, reads a new useRecommendedEcommerceEvents config flag (default false), and routes matching events through the utility before falling back to legacy purchase/custom-event paths. Tests validate all seven mapped events, field normalization, product array construction, required-field warnings, and edge cases.

Changes

Braze Recommended Ecommerce Events

Layer / File(s) Summary
Event mapping constants and field definitions
src/integrations/Braze/ecommerceUtil.js
Defines BRAZE_ECOMMERCE_EVENTS constants, the case-insensitive RS-to-Braze event name map, and per-event and per-product field mapping specifications with required-field flags and fallback source-key chains for seven ecommerce endpoints.
Internal payload construction helpers
src/integrations/Braze/ecommerceUtil.js
Adds truthiness resolution for zero/false values, unmapped-key extraction with cleaning, consumed-key computation for event and product fields (including cart_updated single-product wrapping), per-product field mapping with metadata routing, and required-field collection across payloads.
Public API: getEcommerceMapping, deriveSource, buildEcommerceEventProperties
src/integrations/Braze/ecommerceUtil.js
Exports case-insensitive event name lookup returning mapped Braze event, source normalization to Braze enums with 'web' fallback, and the main payload builder that assembles mapped properties, routes unmapped fields to metadata, validates required fields, logs warnings, and removes undefined/null/empty values.
Feature flag wiring and track dispatch
src/integrations/Braze/browser.js, .size-limit.mjs
Imports the new ecommerce utilities, initializes this.useRecommendedEcommerceEvents from config (default false), adds a conditional branch in track() that derives ecommerce mapping and calls logCustomEvent with built payload before existing logPurchase/generic fallback paths, and increases CDN size limit to accommodate new utilities.
Comprehensive test coverage
__tests__/integrations/Braze/browser.test.js
Adds Jest suite with shared baseConfig and helpers covering all seven mapped events, field transformation and normalization, single-product wrapping for cart operations, empty/null scrubbing, required-field warnings, missing products[] handling, source and action overrides, unmapped event fallback to legacy logCustomEvent, and disabled-flag fallback to logPurchase.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description is comprehensive and well-structured, covering motivation, technical details, event mappings, and implementation notes. However, all validation checkboxes (Cross Browser Tests, Sanity Suite, Security) remain unchecked, indicating the author has not confirmed completion of these required steps. Complete and check the Cross Browser Tests (Chrome, Firefox, IE11), Sanity Suite, and Security validation checkboxes to confirm testing and review are complete before merging.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding support for Braze ecommerce events as a new feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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 opt-in path in the Braze web integration to emit Braze “recommended ecommerce events” (e.g., ecommerce.order_placed) with a structured properties payload, metadata pass-through, and warnings for missing required fields.

Changes:

  • Introduces ecommerceUtil.js to map RS ecommerce track events to Braze recommended event names and build compliant event properties (including products[], source, action, and metadata).
  • Updates Braze track() to use the recommended ecommerce mapping when useRecommendedEcommerceEvents is enabled, otherwise falling back to legacy behavior.
  • Adds unit tests covering mapping behavior, warnings for missing required fields, source override, and legacy fall-through.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js New mapping + payload builder for Braze recommended ecommerce events, including required-field warnings and metadata routing.
packages/analytics-js-integrations/src/integrations/Braze/browser.js Adds feature flag and routes eligible ecommerce track events through the new recommended-event path.
packages/analytics-js-integrations/tests/integrations/Braze/browser.test.js Adds coverage for the new recommended ecommerce events behavior and legacy fall-through scenarios.

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

Comment thread packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js Outdated
Comment thread packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js Outdated
Comment thread packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js Outdated
Comment thread packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js Outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/analytics-js-integrations/__tests__/integrations/Braze/browser.test.js (1)

1090-1094: 💤 Low value

Consider mocking before instantiation for clarity.

The mockBrazeSDK() call happens after creating the Braze instance. While this works correctly (the constructor doesn't access globalThis.braze), it's unconventional and could confuse maintainers. The typical pattern is to set up mocks before instantiating the object under test.

♻️ Suggested refactor
 const buildBraze = (configOverrides = {}) => {
+  mockBrazeSDK();
   const braze = new Braze({ ...baseConfig, ...configOverrides }, {}, {});
-  mockBrazeSDK();
   return braze;
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/analytics-js-integrations/__tests__/integrations/Braze/browser.test.js`
around lines 1090 - 1094, The buildBraze function is calling mockBrazeSDK()
after instantiating the Braze object, but the conventional testing pattern is to
set up mocks before object instantiation. Move the mockBrazeSDK() call to occur
before the new Braze() constructor call within the buildBraze function to follow
standard test setup patterns and improve code clarity for maintainers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js`:
- Around line 196-200: The condition that marks top-level product fields as
consumed for cart_updated events is incorrect because it checks only the event
type (which is always true for cart_updated) rather than whether a products
array actually exists. When a products array is present, the top-level product
fields are not used and should not be marked as consumed, preventing data loss.
Refactor the condition in the block where
consumedKeysFromMapping(ECOMMERCE_PRODUCT_MAPPING) is called to additionally
check whether a products array is actually absent in the properties before
consuming those top-level product field keys.

---

Nitpick comments:
In
`@packages/analytics-js-integrations/__tests__/integrations/Braze/browser.test.js`:
- Around line 1090-1094: The buildBraze function is calling mockBrazeSDK() after
instantiating the Braze object, but the conventional testing pattern is to set
up mocks before object instantiation. Move the mockBrazeSDK() call to occur
before the new Braze() constructor call within the buildBraze function to follow
standard test setup patterns and improve code clarity for maintainers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2c987b33-411b-464d-850e-a01dbba578be

📥 Commits

Reviewing files that changed from the base of the PR and between 4a6af93 and 8d7d21e.

📒 Files selected for processing (3)
  • packages/analytics-js-integrations/__tests__/integrations/Braze/browser.test.js
  • packages/analytics-js-integrations/src/integrations/Braze/browser.js
  • packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js

Comment thread packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js Outdated
@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown

size-limit report 📦

Name Size Delta Limit check
Plugins Module Federation Mapping - Legacy - CDN 330 B 0 B (0% 🟢) 512 B (✅)
Plugins Module Federation Mapping - Modern - CDN 330 B 0 B (0% 🟢) 512 B (✅)
Plugins - Legacy - CDN 13.6 KB 0 B (0% 🟢) 15 KB (✅)
Plugins - Modern - CDN 5.52 KB 0 B (0% 🟢) 6 KB (✅)
Core - Legacy - NPM (ESM) 47.77 KB 0 B (0% 🟢) 50 KB (✅)
Core - Legacy - NPM (CJS) 47.94 KB 0 B (0% 🟢) 50 KB (✅)
Core - Legacy - NPM (UMD) 47.83 KB 0 B (0% 🟢) 50 KB (✅)
Core - Legacy - CDN 47.88 KB 0 B (0% 🟢) 50 KB (✅)
Core - Modern - NPM (ESM) 27.09 KB 0 B (0% 🟢) 28.5 KB (✅)
Core - Modern - NPM (CJS) 27.33 KB 0 B (0% 🟢) 28.5 KB (✅)
Core - Modern - NPM (UMD) 27.14 KB 0 B (0% 🟢) 28.5 KB (✅)
Core - Modern - CDN 27.36 KB 0 B (0% 🟢) 28.5 KB (✅)
Core (Bundled) - Legacy - NPM (ESM) 47.81 KB 0 B (0% 🟢) 50 KB (✅)
Core (Bundled) - Legacy - NPM (CJS) 47.97 KB 0 B (0% 🟢) 50 KB (✅)
Core (Bundled) - Legacy - NPM (UMD) 47.78 KB 0 B (0% 🟢) 50 KB (✅)
Core (Bundled) - Modern - NPM (ESM) 40.35 KB 0 B (0% 🟢) 41.5 KB (✅)
Core (Bundled) - Modern - NPM (CJS) 40.59 KB 0 B (0% 🟢) 42 KB (✅)
Core (Bundled) - Modern - NPM (UMD) 40.42 KB 0 B (0% 🟢) 41.5 KB (✅)
Core (Content Script) - Legacy - NPM (ESM) 47.72 KB 0 B (0% 🟢) 50 KB (✅)
Core (Content Script) - Legacy - NPM (CJS) 47.82 KB 0 B (0% 🟢) 50 KB (✅)
Core (Content Script) - Legacy - NPM (UMD) 47.74 KB 0 B (0% 🟢) 50 KB (✅)
Core (Content Script) - Modern - NPM (ESM) 40.38 KB 0 B (0% 🟢) 41.5 KB (✅)
Core (Content Script) - Modern - NPM (CJS) 40.52 KB 0 B (0% 🟢) 41.5 KB (✅)
Core (Content Script) - Modern - NPM (UMD) 40.32 KB 0 B (0% 🟢) 41.5 KB (✅)
Core (Lite) - Legacy - NPM (ESM) 36.48 KB 0 B (0% 🟢) 39 KB (✅)
Core (Lite) - Legacy - NPM (CJS) 36.69 KB 0 B (0% 🟢) 39 KB (✅)
Core (Lite) - Legacy - NPM (UMD) 36.47 KB 0 B (0% 🟢) 39 KB (✅)
Core (Lite) - Modern - NPM (ESM) 31.8 KB 0 B (0% 🟢) 34 KB (✅)
Core (Lite) - Modern - NPM (CJS) 32.01 KB 0 B (0% 🟢) 34 KB (✅)
Core (Lite) - Modern - NPM (UMD) 31.84 KB 0 B (0% 🟢) 34 KB (✅)
Core (v1.1) - NPM (ESM) 29.77 KB 0 B (0% 🟢) 32 KB (✅)
Core (v1.1) - NPM (CJS) 29.99 KB 0 B (0% 🟢) 32 KB (✅)
Core (v1.1) - NPM (UMD) 29.8 KB 0 B (0% 🟢) 32 KB (✅)
Core (Content Script - v1.1) - NPM (ESM) 29.39 KB 0 B (0% 🟢) 30.5 KB (✅)
Core (Content Script - v1.1) - NPM (CJS) 29.47 KB 0 B (0% 🟢) 30.5 KB (✅)
Core (Content Script - v1.1) - NPM (UMD) 29.37 KB 0 B (0% 🟢) 30.5 KB (✅)
Core (v1.1) - Legacy - CDN 31.24 KB 0 B (0% 🟢) 32.5 KB (✅)
Core (v1.1) - Modern - CDN 29.68 KB 0 B (0% 🟢) 32 KB (✅)
Load Snippet 780 B 0 B (0% 🟢) 1 KB (✅)
All Integrations - Legacy - CDN 97.47 KB 1.21 KB (+1.26% 🔺) 98.5 KB (✅)
All Integrations - Modern - CDN 89.97 KB 1.48 KB (+1.67% 🔺) 93.5 KB (✅)

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 21, 2026

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

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

Comment thread packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 22, 2026

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 22, 2026

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

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

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/analytics-js-integrations/__tests__/integrations/Braze/browser.test.js`:
- Line 1427: Replace all instances of window.braze with globalThis.braze in the
test assertions to maintain consistency with the actual integration code that
dispatches via globalThis.braze. This change is necessary in the assertion at
line 1427 and the range at lines 1440-1446 to ensure the tests remain compatible
with service worker environments where the window object does not exist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a64b8feb-8842-450e-9d83-41796bbc5b96

📥 Commits

Reviewing files that changed from the base of the PR and between a30488d and 0836057.

📒 Files selected for processing (3)
  • packages/analytics-js-integrations/.size-limit.mjs
  • packages/analytics-js-integrations/__tests__/integrations/Braze/browser.test.js
  • packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js
✅ Files skipped from review due to trivial changes (1)
  • packages/analytics-js-integrations/.size-limit.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/analytics-js-integrations/src/integrations/Braze/ecommerceUtil.js

Comment thread packages/analytics-js-integrations/__tests__/integrations/Braze/browser.test.js 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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

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

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

Comment thread packages/analytics-js-integrations/.size-limit.mjs
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 22, 2026
Copilot AI review requested due to automatic review settings June 24, 2026 05:22

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

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

Comment on lines +209 to +214
case FIELD_TYPE.INTEGER:
// `value % 1 === 0` is true only for whole numbers; NaN/Infinity yield NaN and fail.
return typeof value === 'number' && value % 1 === 0;
case FIELD_TYPE.FLOAT:
return typeof value === 'number' && !Number.isNaN(value);
case FIELD_TYPE.STRING_ARRAY:
Comment on lines +329 to +331
.map(raw => {
const item = raw && typeof raw === 'object' ? raw : {};
const product = removeUndefinedAndNullAndEmptyValues(
@sonarqubecloud

Copy link
Copy Markdown

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.

3 participants