Salesforce Commerce Cloud - Custom Code (Controllers & Pipelines)
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 to four parts: templates, client-side JavaScript, controllers (SiteGenesis Controllers version) and pipelines (SiteGenesis Pipelines version).
- Templates
- Client-side JavaScript
- Controllers (SiteGenesis Controllers only)
- Pipelines (SiteGenesis Pipelines only)
Templates
1. cartridge/templates/default/components/header/htmlhead.isml
Paste the following code after the “Google verification feature” as it shown on the screenshot below.
<isinclude template="affirm/affirmheader" />
2. cartridge/templates/default/components/footer/footer_UI.isml
Paste code after the last line:
<isinclude template="affirm/affirmfooter" />
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:
<isaffirmpromo context="cart" fpname="${require('int_affirm/cartridge/scripts/utils/affirmUtils').getFPNameByBasket(pdict.Basket)}">
4. cartridge/templates/default/product/components/options.isml
Add “data-affirm-name” property to the select
component.
<select id="${Option.htmlName}" name="${Option.htmlName}" data-affirm-name="${Option.ID}" class="product-option input-select">
5. cartridge/templates/default/product/productcontent.isml
Paste after “pricing component”:
<isinclude template="util/affirmmodule"/>
<isaffirmpromo context="pdp" fpname="${require('int_affirm/cartridge/scripts/utils/affirmUtils').getFinancingProgramByProduct(pdict.Product, true)}" />
6. cartridge/templates/default/checkout/billing/paymentmethods.isml
Find the following code:
Replace it with the code below:
Insert the following tag after the comment tag "Custom processor":
<isinclude template="affirm/affirmpaymentmethod" />
7. cartridge/templates/default/checkout/summary/summary.isml
Paste the following code after the COSummary-Submit
form:
<isinclude template="affirm/vcndata" />
8. cartridge/templates/default/product/producttile.isml
Paste the code below after the product swatches
block:
<isinclude template="util/affirmmodule"/>
<isaffirmpromo context="plp" fpname="${require('int_affirm/cartridge/scripts/utils/affirmUtils').getFPNameForPLP(pdict.CurrentHttpParameterMap.cgid.value, Product)}" price="${prices}"/>
9. cartridge/templates/default/product/producttopcontentPS.isml
Paste the following code after the div with product-number
class:
<isinclude template="util/affirmmodule"/>
<isaffirmpromo context="pdp" fpname="${require('int_affirm/cartridge/scripts/utils/affirmUtils').getFinancingProgramByProduct(pdict.Product, true)}" />
10. cartridge/templates/default/util/modules.isml
Paste the following after the content asset module import:
<isinclude template="util/affirmmodule"/>
11. cartridge/templates/default/components/order/orderdetails.isml
Replace the div with payment-type
class and isminicreditcard
tag with the code below
<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>
12. cartridge/templates/default/components/order/orderdetailsemail.isml
Replace lines above isminicreditcard
tag (lines 46-50) with the code below:
<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>
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:
<isinclude url="${URLUtils.http('Affirm-Tracking', 'orderId', pdict.Order.orderNo)}" >
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:
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:
if (typeof affirm !== "undefined"){
affirm.ui.refresh();
}
2. cartridge/js/pages/search.js
Within the $('#man').load
jQuery callback include the snippet below:
if (typeof affirm !== "undefined"){
affirm.ui.refresh();
}
3. cartridge/js/pages/product/productSet.js
Update on('click')
of event action with $productSetList
with the extended code:
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:
applicablePaymentMethods = require('*/cartridge/controllers/Affirm').Init(cart, applicablePaymentMethods);
In the same file, find publicStart
function and replace applicablePaymentMethods
assignment with the following:
var applicablePaymentMethods = require('*/cartridge/controllers/Affirm').Init(cart, creditCardList.ApplicablePaymentMethods);
Replace the status
assignment within resetPaymentForms
function with the following block of code:
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;
2. cartridge/controllers/COPlaceOrder.js
Below the saveCCResult
variable and its conditional check, include affirmController
to get Affirm status with the snippet below:
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:
var redirected = require('int_affirm_controllers/cartridge/controllers/Affirm').Redirect();
if (redirected) {
return;
}
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:
Find start node ResetPaymentForms
and add Pipelet nodes as shown below:
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)