---
updatedAt: 2025-11-13T14:37:22.000Z
agentTools:
  siteIndex: https://docs.affirm.com/llms.txt
  projectIndex: https://docs.affirm.com/developers/v1.0-Global-Integration/llms.txt
---

# Controllers & Pipelines Cartridge Installation

# Overview

This page describes changes that should be made to the site for SiteGenesis storefronts. Custom modifications to your core cartridge outlined in this guide can be separated into four parts:

* Templates
* Client-side JavaScript
* Controllers (SiteGenesis Controllers version)
* Pipelines (SiteGenesis Pipelines version)

## Templates

### 1. cartridge/templates/default/components/header/htmlhead.isml

Paste the following code after the  “Google verification feature” as it is shown on the screenshot below.

```html htmlhead.isml
<isinclude template="affirm/affirmheader" />
```

<Image title="cp_1_htmlhead.png" alt={1370} align="center" className="border" width="100%" border={true} src="https://files.readme.io/aa94a8b-cp_1_htmlhead.png" />

### 2. cartridge/templates/default/components/footer/footer\_UI.isml

Paste code after the last line:

```html footer_UI.isml
<isinclude template="affirm/affirmfooter" />
```

![](https://files.readme.io/731fe82-cp_2_footer_UI.png "cp_2_footer_UI.png")

### 3. cartridge/templates/default/checkout/cart/cart.isml

Find the closing tag for the div with `cart-footer` class (line 850). Paste code after the below:

```html cart.isml
<isaffirmpromo context="cart" fpname="${require('int_affirm/cartridge/scripts/utils/affirmUtils').getFPNameByBasket(pdict.Basket)}">
```

<Image title="cp_3_cart.png" alt={1320} align="center" width="smart" src="https://files.readme.io/eee04f7-cp_3_cart.png" />

### 4. cartridge/templates/default/product/components/options.isml

Add `data-affirm-name` property to the `select` component.

```html options.isml
<select id="${Option.htmlName}" name="${Option.htmlName}" data-affirm-name="${Option.ID}" class="product-option input-select">
```

![](https://files.readme.io/2898719-cp_4_options.png "cp_4_options.png")

### 5. cartridge/templates/default/product/productcontent.isml

Paste after “pricing component”:

```html productcontent.isml
<isinclude template="util/affirmmodule"/>
<isaffirmpromo context="pdp" fpname="${require('int_affirm/cartridge/scripts/utils/affirmUtils').getFinancingProgramByProduct(pdict.Product, true)}" />
```

![](https://files.readme.io/7249b7e-cp_5_productcontent.png "cp_5_productcontent.png")

### 6. cartridge/templates/default/checkout/billing/paymentmethods.isml

Find the following code:

![](https://files.readme.io/6b05cec-cp_6_paymentmethods-1.png "cp_6_paymentmethods-1.png")

Replace it with the code below:

![](https://files.readme.io/ee237f1-cp_6_paymentmethods-2.png "cp_6_paymentmethods-2.png")

Insert the following tag after the comment tag "Custom processor":

```html paymentmethods.isml
<isinclude template="affirm/affirmpaymentmethod" />
```

![](https://files.readme.io/cff0e2e-cp_6_paymentmethods-3.png "cp_6_paymentmethods-3.png")

### 7. cartridge/templates/default/checkout/summary/summary.isml

Paste the following code after the `COSummary-Submit` form:

```html summary.isml
<isinclude template="affirm/vcndata" />
```

![](https://files.readme.io/60d0716-cp_7_summary.png "cp_7_summary.png")

### 8. cartridge/templates/default/product/producttile.isml

Paste the code below after the `product swatches` block:

```html producttile.isml
<isinclude template="util/affirmmodule"/>
<isaffirmpromo context="plp" fpname="${require('int_affirm/cartridge/scripts/utils/affirmUtils').getFPNameForPLP(pdict.CurrentHttpParameterMap.cgid.value, Product)}" price="${prices}"/>
```

![](https://files.readme.io/94dad46-cp_8_producttile.png "cp_8_producttile.png")

### 9. cartridge/templates/default/product/producttopcontentPS.isml

Paste the following code after the div with `product-number` class:

```html producttopcontentPS.isml
<isinclude template="util/affirmmodule"/>
<isaffirmpromo context="pdp" fpname="${require('int_affirm/cartridge/scripts/utils/affirmUtils').getFinancingProgramByProduct(pdict.Product, true)}" />
```

![](https://files.readme.io/9a04331-cp_9_producttopcontentPS.png "cp_9_producttopcontentPS.png")

### 10. cartridge/templates/default/util/modules.isml

Paste the following after the content asset module import:

```html modules.isml
<isinclude template="util/affirmmodule"/>
```

![](https://files.readme.io/80957ea-cp_10_modules.png "cp_10_modules.png")

### 11. cartridge/templates/default/components/order/orderdetails.isml

Replace the div with `payment-type` class and `isminicreditcard` tag with the code below:

```html orderdetails.isml
<isif condition="${!paymentInstr.custom.affirmed}">
			<div class="payment-type"><isprint value="${dw.order.PaymentMgr.getPaymentMethod(paymentInstr.paymentMethod).name}" /> </div>
			<isminicreditcard card="${paymentInstr}" show_expiration="${false}"/>
		<iselse/>
			<isaffirmpaymenttype email="${false}"/>
</isif>
```

![](https://files.readme.io/fc107e0-cp_11_orderdetails.png "cp_11_orderdetails.png")

### 12. cartridge/templates/default/components/order/orderdetailsemail.isml

Replace lines above `isminicreditcard` tag (lines 46-50) with the code below:

```html orderdetailsemail.isml
<isif condition="${!paymentInstr.custom.affirmed}">
	<div><isprint value="${dw.order.PaymentMgr.getPaymentMethod(paymentInstr.paymentMethod).name}" /></div>
	<isif condition="${dw.order.PaymentInstrument.METHOD_GIFT_CERTIFICATE.equals(paymentInstr.paymentMethod)}">
		<isprint value="${paymentInstr.maskedGiftCertificateCode}"/><br />
	</isif>
	<isminicreditcard card="${paymentInstr}" show_expiration="${false}"/>
<iselse/>
	<isaffirmpaymenttype email="${true}"/>
</isif>
```

![](https://files.readme.io/1c12aec-cp_12_orderdetailsemail.png "cp_12_orderdetailsemail.png")

### 13. cartridge/templates/default/checkout/confirmation/confirmation.isml

Paste the following code after the close tag of the div with `confirmation message` class to include tracking script template:

```html confirmation.isml
<isinclude url="${URLUtils.http('Affirm-Tracking', 'orderId', pdict.Order.orderNo)}" >
```

![](https://files.readme.io/5308771-cp_13_confirmation.png "cp_13_confirmation.png")

### 14. int\_affirm\_controllers/cartridge/templates/resources/affirm.properties

Find the property `affirm.controllers.cartridge`. Set it as the name of your controllers cartridge (with script files `app.js`, `guard.js`), for example:

```text affirm.properties
affirm.controllers.cartridge=app_storefront_controllers
```

***

## Client-side JavaScript

### 1. cartridge/js/pages/product/variant.js

Update the `ajax.load` within `updateContent` method with the following snippet:

```javascript variant.js
if (typeof affirm !== "undefined"){
    affirm.ui.refresh();
}
```

![](https://files.readme.io/4c25c4d-cp_js_1_variant.png "cp_js_1_variant.png")

### 2. cartridge/js/pages/search.js

Within the `$('#man').load` jQuery callback include the snippet below:

```javascript search.js
if (typeof affirm !== "undefined"){
    affirm.ui.refresh();
}
```

![](https://files.readme.io/aa7df5d-cp_js_2_search.png "cp_js_2_search.png")

### 3. cartridge/js/pages/product/productSet.js

Update `on('click')` of event action with `$productSetList` with the extended code:

```javascript productSet.js
var updateAffirmItems = function($container, oldSKU) {
        var affirmItem = affirmItems.find(function (item) {
            return item.sku === oldSKU;
        });
 
        affirmItem.sku = $container.find('input[name=pid]').first().val();
    }
 
var updateBuyWithAffirmButton = function () {
        if ($productSetList.find('.add-to-cart[disabled]').length > 0) {
            $('#js-affirm-checkout-now').hide();
        } else {
            $('#js-affirm-checkout-now').show();
            document.dispatchEvent(new CustomEvent('affirm-checkout-button-rendered')); 
        }
            };
 
    // click on swatch for product set
    $productSetList.on('click', '.product-set-item .swatchanchor', function (e) {
        e.preventDefault();
        if ($(this).parents('li').hasClass('unselectable')) { return; }
        var url = Urls.getSetItem + this.search;
        var $container = $(this).closest('.product-set-item');
        var qty = $container.find('form input[name="Quantity"]').first().val();
 
        var oldSKU = $container.find('input[name=pid]').first().val();
        ajax.load({
            url: util.appendParamToURL(url, 'Quantity', isNaN(qty) ? '1' : qty),
            target: $container,
            callback: function () {
                updateAddToCartButtons();
                updateAffirmItems($container, oldSKU);
                updateBuyWithAffirmButton();
                tooltip.init();
            }
        });
    });
```

> 📘 Important
>
> To properly render “affirm-as-low” on PDP, PLP and Cart, at the end of handle functions that influence price on basket (ajax product price change, quantity based price change, pagination, search, add-on price change etc.) must call the `affirm.ui.refresh` function.

> 👍
>
> Make sure to rebuild client JS after making modifications.

***

## Controllers (SiteGenesis Controllers)

### 1. cartridge/controllers/COBilling.js

Reassign `applicablePaymentMethods` within `initCreditCardList` function with the following code:

```javascript COBilling.js
applicablePaymentMethods = require('*/cartridge/controllers/Affirm').Init(cart, applicablePaymentMethods);
```

![](https://files.readme.io/0235777-controllers_1_COBilling-1.png "controllers_1_COBilling-1.png")

In the same file, find `publicStart` function and replace `applicablePaymentMethods` assignment with the following:

```javascript COBilling.js
var applicablePaymentMethods = require('*/cartridge/controllers/Affirm').Init(cart, creditCardList.ApplicablePaymentMethods);
```

![](https://files.readme.io/3d87682-controllers_1_COBilling-2.png "controllers_1_COBilling-2.png")

Replace the `status` assignment within `resetPaymentForms` function with the following block of code:

```javascript COBilling.js
var status = Transaction.wrap(function () {
        if (app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals('PayPal')) {
            app.getForm('billing').object.paymentMethods.creditCard.clearFormElement();
            app.getForm('billing').object.paymentMethods.bml.clearFormElement();

            cart.removePaymentInstruments(cart.getPaymentInstruments(PaymentInstrument.METHOD_CREDIT_CARD));
            cart.removePaymentInstruments(cart.getPaymentInstruments(PaymentInstrument.METHOD_BML));
            cart.removePaymentInstruments(cart.getPaymentInstruments('Affirm'));
        } else if (app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(PaymentInstrument.METHOD_CREDIT_CARD)) {
            app.getForm('billing').object.paymentMethods.bml.clearFormElement();

            cart.removePaymentInstruments(cart.getPaymentInstruments(PaymentInstrument.METHOD_BML));
            cart.removePaymentInstruments(cart.getPaymentInstruments('PayPal'));
            cart.removePaymentInstruments(cart.getPaymentInstruments('Affirm'));
        } else if (app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals(PaymentInstrument.METHOD_BML)) {
            app.getForm('billing').object.paymentMethods.creditCard.clearFormElement();

            if (!app.getForm('billing').object.paymentMethods.bml.ssn.valid) {
                return false;
            }
            cart.removePaymentInstruments(cart.getPaymentInstruments(PaymentInstrument.METHOD_CREDIT_CARD));
            cart.removePaymentInstruments(cart.getPaymentInstruments('PayPal'));
            cart.removePaymentInstruments(cart.getPaymentInstruments('Affirm'));
        } else if (app.getForm('billing').object.paymentMethods.selectedPaymentMethodID.value.equals('Affirm')) {
        	cart.removePaymentInstruments(cart.getPaymentInstruments(PaymentInstrument.METHOD_CREDIT_CARD));
            cart.removePaymentInstruments(cart.getPaymentInstruments(PaymentInstrument.METHOD_BML));
            cart.removePaymentInstruments(cart.getPaymentInstruments('PayPal'));
        }
        return true;
    });

    return status;
```

![](https://files.readme.io/6f4c829-controllers_1_COBilling-3.png "controllers_1_COBilling-3.png")

### 2. cartridge/controllers/COPlaceOrder.js

Below the `saveCCResult` variable and its conditional check, include `affirmController` to get Affirm status with the snippet below:

```javascript COPlaceOrder.js
var affirmController = require('int_affirm_controllers/cartridge/controllers/Affirm');
var affirmCheck = affirmController.CheckCart(cart);
if (affirmCheck.status.error) {
	return {
		error: true,
		PlaceOrderError: affirmCheck.status
	};
}
```

### 3. cartridge/controllers/COSummary.js

Go to `submit` function. Add the following at the beginning of the function:

```javascript COSummary.js
var redirected = require('int_affirm_controllers/cartridge/controllers/Affirm').Redirect();
if (redirected) {
	return;
}
```

![](https://files.readme.io/6315f17-controllers_3_COSummary.png "controllers_3_COSummary.png")

***

## Pipelines (SiteGenesis Pipelines)

### 1. cartridge/pipelines/COBilling.xml

Find the start node `InitCreditCardList` and add call node (Affirm-Init, int\_affirm\_pipelines) after second Assign node:

<Image title="pipelines_1_COBilling_1.png" alt={529} align="center" width="smart" src="https://files.readme.io/34ccde1-pipelines_1_COBilling_1.png">
  pipelines\_1\_COBilling\_1\_Affirm-Init
</Image>

Find start node `ResetPaymentForms` and add Pipelet nodes as shown below:

<Image title="pipelines_1_COBilling_2.png" alt={722} align="center" src="https://files.readme.io/b0ff01a-pipelines_1_COBilling_2.png">
  pipelines\_1\_COBilling\_2\_ResetPaymentForms
</Image>

In the same pipeline create an additional branch:\
a. Decision node – Decision Key: `!CurrentForms.billing.paymentMethods.selectedPaymentMethodID.value.equals('Affirm')`\
b. ClearFormElement Pipelet – FormElement: `CurrentForms.billing.paymentMethods.creditCard`\
c. ClearFormElement Pipelet – FormElement: `CurrentForms.billing.paymentMethods.bml`\
d. `RemoveBasketPaymentInstrument` Pipelet – PaymentInstruments: `Basket.getPaymentInstruments(dw.order.PaymentInstrument.METHOD_CREDIT_CARD)`\
e. `RemoveBasketPaymentInstrument` Pipelet – PaymentInstruments: `Basket.getPaymentInstruments( dw.order.PaymentInstrument.METHOD_BML)`

<Image title="pipelines_1_COBilling_4.png" alt={745} align="center" src="https://files.readme.io/dfce965-pipelines_1_COBilling_4.png">
  pipelines\_1\_COBilling\_4\_ResetPaymentForms\_additional\_branch
</Image>

# Sibling pages

* [Installation](https://docs.affirm.com/developers/v1.0-Global-Integration/docs/sfcc-installation.md)
* [Configuring Affirm for SFCC](https://docs.affirm.com/developers/v1.0-Global-Integration/docs/configuring-affirm-for-sfcc.md)
* [SFRA Cartridge Installation](https://docs.affirm.com/developers/v1.0-Global-Integration/docs/sfra-cartridge-installation.md)
* [Transaction Management with Jobs](https://docs.affirm.com/developers/v1.0-Global-Integration/docs/transaction-management-with-jobs.md)
* [SFCC FAQ](https://docs.affirm.com/developers/v1.0-Global-Integration/docs/sfcc-faq.md)