← Voltar aos Artigos

Salesforce Commerce Cloud: Pixel e CAPI do OpenAI Ads para SFCC: Configuração completa

Guia corporativo para implementar o pixel e a API de conversões do OpenAI Ads no Salesforce Commerce Cloud (B2C) com cartuchos e ISML.

2026-03-27 • eCommerce Platforms

Salesforce Commerce Cloud (SFCC / B2C Commerce) handles some of the highest transaction volumes in global retail. At enterprise scale, a 15% discrepancy in conversion attribution translates to hundreds of thousands of dollars in misallocated ad spend. When shoppers click ads in ChatGPT and purchase on SFCC, Safari's 24-hour ITP limits, browser privacy features, and checkout drop-offs prevent front-end pixels from reporting complete revenue.

Enterprise brands cannot afford to rely on client-side JavaScript alone.

The proven architecture for SFCC is building a dedicated integration cartridge (int_openai_ads). You place the browser pixel in htmlHead.isml and the order confirmation template for immediate attribution, then wire the SFCC Service Framework (dw.svc.LocalServiceRegistry) into the checkout pipeline to dispatch server-to-server events to https://bzr.openai.com/v1/events. Passing a shared event_id (sfcc_order_{orderNo}) ensures complete deduplication and total tracking accuracy.

Storefront Browsing (SFCC Pipelines / Controllers)
       │
       ▼
[SFCC htmlHead.isml] ──(bzrcdn.openai.com)──► Client Pixel (Pageview, ViewContent, AddToCart)
       │
       ▼ Order Confirmation ISML Template
Browser Pixel Purchase (event_id: sfcc_order_00018492)
       │
       ▼ dw.order.Order Confirmation Hook
[int_openai_ads Service Framework]
       │
       ▼ cURL / HTTPClient POST (event_id: sfcc_order_00018492)
OpenAI Ads Conversions API (https://bzr.openai.com/v1/events)

Part 1: Storefront Cartridge Integration (ISML)

Step 1: Base Pixel in htmlHead.isml

In cartridges/int_openai_ads/cartridge/templates/default/common/htmlHead.isml:

<iscontent type="text/html" charset="UTF-8" compact="true"/>
<isset name="openAiPixelId" value="${dw.system.Site.current.getCustomPreferenceValue('openAiAdsPixelId')}" scope="page" />
<isset name="openAiEnabled" value="${dw.system.Site.current.getCustomPreferenceValue('openAiAdsEnabled')}" scope="page" />

<isif condition="${openAiEnabled && !empty(openAiPixelId)}">
  <script>
    !function(w,d,e,u,t,s){if(w.openaiAds)return;t=w.openaiAds=function(){
    t.callMethod?t.callMethod.apply(t,arguments):t.queue.push(arguments)};
    if(!w._openaiAds)w._openaiAds=t;t.push=t;t.loaded=!0;t.version='1.0';
    t.queue=[];s=d.createElement(e);s.async=!0;s.src=u;
    var f=d.getElementsByTagName(e)[0];f.parentNode.insertBefore(s,f);
    }(window,document,'script','https://bzrcdn.openai.com/pixel.js');

    openaiAds('init', '<isprint value="${openAiPixelId}" encoding="off"/>');
    openaiAds('track', 'PageView');
  </script>
</isif>

Step 2: Client Purchase Event on Confirmation

In cartridges/int_openai_ads/cartridge/templates/default/checkout/confirmation/confirmation.isml:

<isif condition="${openAiEnabled && !empty(pdict.order)}">
  <script>
    document.addEventListener('DOMContentLoaded', function () {
      if (window.openaiAds) {
        var orderValueCents = Math.round(<isprint value="${pdict.order.totalGrossPrice.value}" encoding="off"/> * 100);
        var orderNo = '<isprint value="${pdict.order.orderNo}" encoding="off"/>';
        var dedupeId = 'sfcc_order_' + orderNo;

        window.openaiAds('track', 'Purchase', {
          currency: '<isprint value="${pdict.order.currencyCode}" encoding="off"/>',
          value: orderValueCents,
          order_id: orderNo,
          content_type: 'product'
        }, {
          event_id: dedupeId
        });
      }
    });
  </script>
</isif>

Part 2: Backend CAPI via SFCC Service Framework

Step 1: Register Service in OpenAiAdsService.js

Create cartridges/int_openai_ads/cartridge/scripts/services/OpenAiAdsService.js:

'use strict';

var LocalServiceRegistry = require('dw/svc/LocalServiceRegistry');

var openAiAdsService = LocalServiceRegistry.createService('comercio.openai.ads.capi', {
    createRequest: function (svc, params) {
        svc.setRequestMethod('POST');
        svc.addHeader('Content-Type', 'application/json');
        svc.addHeader('Authorization', 'Bearer ' + params.apiToken);
        svc.setURL('https://bzr.openai.com/v1/events');
        return JSON.stringify(params.payload);
    },
    parseResponse: function (svc, client) {
        return client.text;
    },
    mockCall: function () {
        return {
            statusCode: 200,
            statusMessage: 'Success',
            text: '{"status":"mock_success"}'
        };
    }
});

module.exports = openAiAdsService;

Step 2: Dispatch Purchase in Order Hook

Create cartridges/int_openai_ads/cartridge/scripts/hooks/orderHooks.js:

'use strict';

var MessageDigest = require('dw/crypto/MessageDigest');
var Encoding = require('dw/crypto/Encoding');
var Bytes = require('dw/util/Bytes');
var Site = require('dw/system/Site');
var Logger = require('dw/system/Logger').getLogger('OpenAiAds', 'CAPI');
var openAiAdsService = require('~/cartridge/scripts/services/OpenAiAdsService');

function hashSha256(value) {
    if (!value) return null;
    var digest = new MessageDigest(MessageDigest.DIGEST_SHA_256);
    var cleanVal = value.trim().toLowerCase();
    return Encoding.toHex(digest.digestBytes(new Bytes(cleanVal, 'UTF-8')));
}

function postOrderToCapi(order) {
    var site = Site.current;
    if (!site.getCustomPreferenceValue('openAiAdsEnabled')) {
        return;
    }

    var apiToken = site.getCustomPreferenceValue('openAiAdsApiToken');
    if (!apiToken) {
        Logger.error('Missing openAiAdsApiToken preference');
        return;
    }

    var orderNo = order.getOrderNo();
    var dedupeId = 'sfcc_order_' + orderNo;
    var emailHash = hashSha256(order.getCustomerEmail());
    
    var phoneHash = null;
    var billingAddress = order.getBillingAddress();
    if (billingAddress && billingAddress.getPhone()) {
        phoneHash = hashSha256(billingAddress.getPhone().replace(/[^0-9]/g, ''));
    }

    var valueMinorUnits = Math.round(order.getTotalGrossPrice().getValue() * 100);
    var currency = order.getCurrencyCode();

    var productLineItems = order.getProductLineItems().toArray();
    var contentIds = [];
    for (var i = 0; i < productLineItems.length; i++) {
        contentIds.push(productLineItems[i].getProductID());
    }

    var payload = {
        data: [{
            event_name: 'Purchase',
            event_time: Math.floor(Date.now() / 1000),
            event_id: dedupeId,
            user_data: {
                em: emailHash,
                ph: phoneHash,
                country: billingAddress ? hashSha256(billingAddress.getCountryCode().getValue()) : null
            },
            custom_data: {
                currency: currency,
                value: valueMinorUnits,
                order_id: orderNo,
                content_ids: contentIds,
                content_type: 'product'
            },
            action_source: 'system_generated'
        }]
    };

    try {
        var result = openAiAdsService.call({
            apiToken: apiToken,
            payload: payload
        });
        if (!result.isOk()) {
            Logger.error('CAPI Call failed for order {0}: {1}', orderNo, result.getErrorMessage());
        }
    } catch (e) {
        Logger.error('Exception calling OpenAI Ads CAPI: {0}', e.message);
    }
}

exports.postOrderToCapi = postOrderToCapi;

Verification & Enterprise QA

  1. Service Credentials: Configure comercio.openai.ads.capi credentials inside Business Manager > Administration > Operations > Services.
  2. Log Inspection: Check custom error logs (OpenAiAds-CAPI-*.log) for HTTP 200 confirmations.
  3. Deduplication Validation: Validate in OpenAI Ads Event Manager that storefront browser purchases and backend service purchases fuse cleanly under sfcc_order_{orderNo}.

Frequently Asked Questions

How is OpenAI Ads Pixel integrated into Salesforce B2C Commerce (SFCC)?

Create a custom cartridge (e.g., int_openai_ads) and extend common/htmlHead.isml to include the base pixel loader, driven by Site Preferences for the Pixel ID and enablement flags.

Where should server-side CAPI calls be triggered in SFCC?

Implement a hook for dw.order.OrderMgr after successful order placement (or in Order-Confirm controller / COPlaceOrder-Submit hook) using the SFCC Service Framework (dw.svc.LocalServiceRegistry).

How does SFCC handle currency and minor units for OpenAI Ads CAPI?

Use dw.value.Money to extract totalGrossPrice, multiply value by 100 as an integer, and send order.currencyCode in uppercase.

How do you guarantee event deduplication between SFCC storefront ISML and backend service calls?

Generate the event_id as sfcc_order_ + order.orderNo in both the ISML confirmation template script and the server-side Service Framework call.