Skip to content

Conversation

@jaissica12
Copy link
Contributor

@jaissica12 jaissica12 commented Nov 7, 2025

Instructions

  1. PR target branch should be against development
  2. PR title name should follow this format: https://github.com/mParticle/mparticle-workflows/blob/main/.github/workflows/pr-title-check.yml
  3. PR branch prefix should follow this format: https://github.com/mParticle/mparticle-workflows/blob/main/.github/workflows/pr-branch-check-name.yml

Summary

Add Product Attribute Mapping for Facebook Purchase Events
- Implement buildProductContents() to create nested contents array for Purchase events
- Add productAttributeMapping setting for configurable field mapping
- Map TransactionId to order_id parameter
- Support mapping both product fields and custom attributes
- Add test coverage for the changes

  • Screenshot 2025-11-10 at 10 20 14 PM
productAttributeMapping: {
                          'Name': 'test_name',               // product.Name → test_name
                          'Brand': 'test_brand',             // product.Brand → test_brand
                          'Price': 'test_price',             // product.Price → test_price
                          'category': 'test_category'        // product.Attributes.category → test_category
                 }

Testing Plan

  • Was this tested locally? If not, explain why.
  • {explain how this has been tested, and what, if any, additional testing should be done}

Reference Issue (For mParticle employees only. Ignore if you are an outside contributor)

@jaissica12 jaissica12 changed the base branch from master to development November 7, 2025 21:43
@jaissica12 jaissica12 marked this pull request as ready for review November 7, 2025 21:58
@jaissica12 jaissica12 changed the base branch from development to master November 7, 2025 21:59
@rmi22186 rmi22186 self-requested a review November 7, 2025 22:03
@rmi22186
Copy link
Collaborator

Can you add tests?

// Resolve a simple product key by checking top-level first, then Attributes bag
function getField(product, key) {
if (!product || !key) return undefined;
if (Object.prototype.hasOwnProperty.call(product, key)) {
Copy link
Collaborator

@rmi22186 rmi22186 Nov 11, 2025

Choose a reason for hiding this comment

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

It looks like this is prioritizing the value of the attribute at the Product level vs the Product.Attributes level. I don't think this matters because it is likely that if a customer puts a product.attribute that is the same as the Product level attribute, that the value would be the same.

Just to call out though - for the customer who requested this, the launchpad/chats say that they want to pass in the following:
product_type: product.custom_attributes.category

This is interesting, because category is actually one of our product level keys as well (see docs here). However, when you call mParticle.eCommerce.createProduct(), what is returned is a product with a Titlecase key, ie:

var product1 = mParticle.eCommerce.createProduct(
    'Double Room - Econ Rate',  // Name
    'econ-1',                   // SKU
    100.00,                     // Price
    4,                          // Quantity
    'variant',                  // Variant
    'room',                     // Category
    'lodge-o-rama',             // Brand
    'banner',                   // Position
    null,                       // Coupon code
    customProductAttributes     // The custom attributes defined in a separate variable above
);

makes:

Image

So if the customer puts category, since it's lowercase it will overlook Product.Category and then look at product.Attributes.category.

But I wouldn't expect it to be a different value at the end of the day. This comment is more digging in deeper as an FYI

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the detailed explanation!
Our implementation prioritizes standard product fields over custom attributes in the mapping logic. The case-sensitive key matching naturally separates these two namespaces, allowing customers to map both without conflicts. I've added test coverage for both Product.Category and Product.Attributes.category to validate this behavior and ensure both mapping types work correctly.

// Check product field first
if (product.hasOwnProperty(sourceField)) {
    value = product[sourceField];
}
// Then check custom attributes
else if (product.Attributes && product.Attributes[sourceField]) {
    value = product.Attributes[sourceField];
}

Copy link
Collaborator

@rmi22186 rmi22186 left a comment

Choose a reason for hiding this comment

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

Added all my comments. Please review and lmk if you have any questions

@jaissica12 jaissica12 requested a review from rmi22186 November 11, 2025 14:43
test/tests.js Outdated
Comment on lines 866 to 873
productAttributeMapping: JSON.stringify({
'Name': 'custom_name',
'Brand': 'custom_brand',
'Price': 'custom_price',
'category': 'custom_attribute_category',
'Category': 'custom_category',

})
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would use a real copied and pasted setting, like from https://jssdk-origin-qa1.qa.corp.mparticle.com/js/v2/9e77ff19b9fa2b4fa33fa0ef322addf4/config

"productAttributeMapping": "[{"jsmap":"3373707","map":"Name","maptype":"ProductAttributeSelector.Name","value":"test_name"},{"jsmap":"93997959","map":"Brand","maptype":"ProductAttributeSelector.Name","value":"test_brand"},{"jsmap":"3322014","map":"list","maptype":"ProductAttributeSelector.Name","value":"test_list"}]"

Copy link
Collaborator

Choose a reason for hiding this comment

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

You can change the map and value in there, but at least this way you have the structure of a rela string that is returned.

Copy link
Contributor Author

@jaissica12 jaissica12 Nov 11, 2025

Choose a reason for hiding this comment

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

I agree, and this helped with debugging as well! Updated the tests to use real settings.

@jaissica12 jaissica12 requested a review from rmi22186 November 11, 2025 16:47
Copy link
Collaborator

@rmi22186 rmi22186 left a comment

Choose a reason for hiding this comment

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

one minor comment

jaissica12 and others added 2 commits November 11, 2025 14:23
@rmi22186
Copy link
Collaborator

@jaissica12 - LGTM. Only thing is please change the title from feat: [SDKE-482] support custom product attributes to feat: SDKE-482 support custom product attributes to match how we do core SDK (although we've been inconsistent there)

@jaissica12 jaissica12 changed the title feat: [SDKE-482] support custom product attributes feat: SDKE-482 support custom product attributes Nov 11, 2025
@rmi22186 rmi22186 changed the base branch from master to development November 12, 2025 19:29
@rmi22186 rmi22186 merged commit a61adcb into mparticle-integrations:development Nov 12, 2025
2 checks passed
github-actions bot pushed a commit that referenced this pull request Nov 13, 2025
# [2.2.0](v2.1.0...v2.2.0) (2025-11-13)

### Bug Fixes

* Correct variable declarations, add ESM module ([#46](#46)) ([3fa1b70](3fa1b70))

### Features

* SDKE-482 support custom product attributes ([#49](#49)) ([97f1086](97f1086))
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