# Multiple Checkout Items
In the previous guide, we showed the basic SDK code to send product and payment confirmation events on a single product.
In reality, users usually purchase multiple products, or multiple items of the same product.
There are two distinct use-cases for multiple checkout items.
- A user purchased several identical items. For example, 5 iPhone X covers.
- A user purchased several items of different kinds. For example, 2 iPhone X covers, and 3 iPhone X chargers.
In both use-cases, you should first decide whether each sold item should be considered as an individual conversion, or should any number of identical item sales are considered a single conversion.
Important
Each call to QL.sendConfirmationEvent
creates a single conversion event in QL's BI database, and is treated
as a single unit of sale. Units of sale are used to calculate conversion rate and aggregated number of sales across QL's UI.
# Multiple checkout items - Distinct conversion events
When a user purchased several items and we want to count each item as a distinct conversion event, we create an array of sold products, and add each sale to that array, along with its sale price.
app/controllers/checkout_controller.rb
class CheckoutController < ApplicationController
# GET /checkout/finish - renders successful checkout
def finish
checkoutProducts = session[:checkoutProducts] # read checked out products from session
@soldProducts = []
checkoutProducts.each do |product|
# product is a hash table: {id: productId, salePrice: salePrice}
productFromDB = Product.find(product[:id])
productId = productFromDB.ean # use product ean as productId
# push product to soldProducts
@soldProducts.push({
id: productId,
salePrice: product[:salePrice]
})
end
@clientKey = 'myvirtualstore'
render('finish') # explicit call to render the payment confirmation view
end
end
Sale price
In reality sale prices can be different event when the same item is sold multiple times. For example Buy 2 and get the 3rd one free. You should set the sale price of each item to the actual price it was purchased in.
# Multiple checkout items - Summed conversion events
When a user purchased several items and we want to count all items of the same kind (product ID) as a single conversion event, we create an array of sold products, and add an entry for each product kind (product ID), along with its sale price multiplied by the number of sold items.
app/controllers/checkout_controller.rb
class CheckoutController < ApplicationController
# GET /checkout/finish - renders successful checkout
def finish
checkoutProducts = session[:checkoutProducts] # read checked out products from session
@soldProducts = []
checkoutProducts.each do |product|
# product is a hash table: {id: productId, salePrice: salePrice, soldItems: soldItems}
productFromDB = Product.find(product[:id])
productId = productFromDB.ean # use product ean as productId
# push product to soldProducts
@soldProducts.push({
id: productId,
salePrice: product[:salePrice] * product[:soldItems]
})
end
@clientKey = 'myvirtualstore'
render('finish') # explicit call to render the payment confirmation view
end
end
Note
As with the previous example, we save the sale information in the user's session for simplicity. In reality you might save this information in your DB or a cache layer like Redis.
# Sending events with the SDK
With our controller code in place, we can now modify our payment confirmation view to send multiple items to QL using the SDK.
Note that the @soldProducts
array is serialized into JSON, and then iterated over, calling the QL.sendConfirmationEvent
method
for each product in the array.
app/views/checkout/finish.erb
<div>
<p>Your payment has been received!</p>
<!-- rest of HTML is redacted for simplicity -->
</div>
<!-- ADD QL's SDK at the bottom of the page template -->
<script>
window.QLAsync = function(QL){
var clientKey = '<%= @clientKey %>',
soldProducts = JSON.parse('<%= @soldProducts.to_json %>');
QL.init(clientKey);
// iterate over soldProducts and send each one to QL using the SDK
soldProducts.forEach(function(product) {
QL.sendConfirmationEvent(product.productId, parseFloat(product.salePrice, 10));
});
}
</script>
<script src="//d3jdlwnuo8nsnr.cloudfront.net/sdk/v2.1/ql.js"></script>
# Google Tag Manager
The above example can be modified to work on Google Tag Manager by pushing the @soldProducts
array into GTM's dataLayer
.
app/views/checkout/finish.erb
<div>
<p>Your payment has been received!</p>
<!-- rest of HTML is redacted for simplicity -->
</div>
<!-- initialize GTM dataLayer -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'clientKey': '<%= @clientKey %>',
'soldProducts': '<%= @soldProducts.to_json %>'
}]);
</script>
Modify your GTM embed code for the Payment Confirmation Page as follows:
<script>
window.QLAsync = function(QL){
var clientKey = '{{ clientKey }}',
soldProducts = JSON.parse('{{ soldProducts }}');
QL.init(clientKey);
// iterate over soldProducts and send each one to QL using the SDK
soldProducts.forEach(function(product) {
QL.sendConfirmationEvent(product.productId, parseFloat(product.salePrice, 10));
});
}
</script>
<script src="//d3jdlwnuo8nsnr.cloudfront.net/sdk/v2.1/ql.js"></script>