Checkout Tag

{exp:store:checkout}
    <!-- checkout form -->
{/exp:store:checkout}

This tag handles the entire checkout process, from updating item quantities, to billing and shipping details, through to submitting and paying for the order. It is extremely flexible, and you can template the process however you like - either as a single, or as a multi step process. You can also choose which step of the process will require users to log in, or simply allow anonymous orders.

Think of the user’s cart as being like a session. With Expresso Store, your visitors add items to their cart. When they get to the checkout, they update their cart with billing and shipping details, and the cart totals are recalculated to reflect their relevant tax and shipping costs.

When the user reaches the final step of your checkout, the cart is converted in to an order. At this point, if any payment details were submitted on the final page of the checkout, these are sent to the relevant payment gateway, and the user will be taken to your payment success (or failure) page.

Checkout Tag Parameters

next

The next step of a multi step checkout. If the user clicks an input button with name=”next”, and current form validates, the user will be redirected to this location.

{exp:store:checkout next="checkout/confirm"}
    <input type="submit" name="next" value="Confirm Order" />
{/exp:store:checkout}

return

Where to redirect the user to once the order is submitted. You only need to add this parameter to the last step of your checkout process. The order will only be submitted when the user clicks an input button with name=”submit”, this is to differentiate between other buttons in the form.

Optionally, you may redirect to an order-specific confirmation page (this is the normal setup). The variables ORDER_ID and ORDER_HASH can be used in this parameter to customize your return location.

{exp:store:checkout return="order/ORDER_HASH"}
    <input type="submit" name="submit" value="Place Order" />
{/exp:store:checkout}

Alternatively, since 1.3.0 you may name your submit button “commit”. This allows compatibility when using javascript to interact with your form on certain browsers.

form_id

Set an id attribute on the generated HTML form.

form_name

Set a name attribute on the generated HTML form.

form_class

Set a class attribute on the generated HTML form.

payment_method

Set the payment method of the current cart. This can also be specified via a hidden input or select drop-down if you would like to give the user a choice of payment methods.

register_member

If set to yes, create a member account for this user when the order is complete. This can also be specified as a form input field.

secure

If set to yes, ensures the current page is displayed over a secure SSL (HTTPS) connection. If the page was not displayed over HTTPS, the user is redirected to a secure version. The current form action is also submitted over HTTPS. If you accept inline credit card details on the final page of the checkout, this option must be set. If you configure “Require SSL connection for checkout and order tags” in the Store settings, all tags will have this option by default.

require

Specify a pipe-separated list of required fields. All order fields can be made required using this tag. In addition, a shorthand syntax is available if both billing and shipping details are required. For example, the following parameter:

{exp:store:checkout require="name|address1|address2|region|country|postcode"}

is equivalent to typing:

{exp:store:checkout require="billing_name|billing_address1|billing_address2|billing_region|billing_country|billing_postcode|
  shipping_name|shipping_address1|shipping_address2|shipping_region|shipping_country|shipping_postcode"}

Much nicer, right?

rules:field_name

As well as using the require=”field_name” parameter, the longer SafeCracker-style syntax is also available. For each field, any of the CodeIgniter Form Validation Rules may be specified. If this syntax is used in addition to the require=”field_name” parameter, both will apply. Note that the order_email field is already run through the valid_email rule, you don’t need to manually specify it.

rules:billing_name="required"
rules:billing_phone="numeric"
rules:billing_postcode="required|min_length[5]|max_length[5]"

error_handling

By default, validation errors are displayed using the ugly standard ExpressionEngine error template. To alleviate this issue, add error_handling=”inline” to your template. Field-specific error messages will then become available in the form {error:field_name}, which you can add to your template code in appropriate places. If you are having trouble with your form not submitting, the first thing you should try is removing the error_handling=”inline” parameter from your template, as often this is caused by validation errors which you have forgotten to display error messages for.

error_delimiters

You can optionally specify HTML to wrap around your inline error messages. This should be specified as two pipe-separated elements. If do not have error_handling=”inline” on your checkout tag, this parameter will have no effect.

error_delimiters='<span class="notice">|</span>'

disable_javascript

When set to yes, this disables any automatic javascript output by the tag.

Checkout Tag Variables

Items Loop

Loop through the order items. Inside the items loop, most product variables are available. All prices may be appended with _val to display the unformatted value, _inc_tax to display the tax-inclusive price, and _inc_tax_val if you want to get really fancy.

{items}
    <!-- item details -->
{/items}

Inside the {items} loop, you can use the following variables.

entry_id

The entry id of this item. If you need to access other custom fields associated with this item, you can feed the entry id into a channel entries loop:

{items}
  {exp:channel:entries entry_id="{entry_id}"}
    {my_custom_field}
  {/exp:channel:entries}
{/items}

sku

The product SKU.

title

The product entry title.

url_title

The product entry URL title.

price

The applicable price of the product, (equal to the sale price if the product is on sale, otherwise the regular price).

regular_price

The regular price of the product, regardless of whether it is currently on sale.

sale_price

The sale price of the product, regardless of whether it is currently on sale.

if on_sale

True if the product is currently on sale.

handling

The applicable handling surcharge (if the user has purchased multiple items, the handling surcharge will be multiplied by the item quantity).

if free_shipping

True if the product has free shipping selected.

modifiers Variable Pair

Displays the selected item modifiers for the product. Inside the modifiers loop, you can use the following variables:

  • {modifier_name} - The name of the modifier group.
  • {modifier_value} - The selected option (or value of text modifiers).
  • {price_mod} - The amount added to the base product price for this modifier.

you_save

The dollar discount value if the product is on sale.

you_save_percent

The percentage discount value if the product is on sale, rounded to the nearest whole number.

item_qty

The number of this product the user has in their cart.

item_subtotal

The item price multiplied by the item quantity.

item_tax

The total tax applicable to this item.

item_total

The total for this item, including tax and any handling charges.

Updating Quantities

To update quantities of existing line items in the cart, you must template inputs on your checkout form, inside the {items} loop. Normally you would display this in a table layout.

The special {key} variable is available inside the {items} loop to use as an index for your input name. This is required, as it tells Store which line item you want to update the quantity of.

<table>
    {items}
        <tr>
            <td>{title}</td>
            <td>{price}</td>
            <td>
                <input name="items[{key}][item_qty]" value="{item_qty}" />
            </td>
            <td>{item_subtotal}</td>
        </tr>
    {/items}
</table>

Removing Items

To remove items from your cart, there are two options. You can either submit the item_qty field above as 0, or alternatively, you can use the remove_items input field. The remove_items input is useful if you want to display a checkbox:

<table>
    {items}
        <tr>
            <td>{title}</td>
            <td>
                <input type="checkbox" name="remove_items[{key}]" value="1" /> Remove {title}
            </td>
        </tr>
    {/items}
</table>

Always set the checkbox value to 1. If the customer doesn’t check the field, the value won’t be submitted, so it won’t cause any unexpected side effects on your checkout form.

You could also template the remove_items input as a form submit button, using the same name.

Order Details

order_qty

The total number of items in the cart.

order_subtotal

The total of all items in the cart.

order_subtotal_tax

The total tax applicable to the order’s subtotal.

order_subtotal_inc_shipping

The order subtotal plus any shipping and handling charges.

order_shipping

The total shipping and handling charges.

order_shipping_tax

The tax applicable to shipping charges.

order_discount

The total discount given by any applicable promo codes.

order_discount_tax

The total tax saved by applicable promo codes.

order_tax

The total tax applicable to this order.

order_total

The final order total, including all shipping, discounts and taxes.

order_email

The email address for this order (required).

accept_terms

If you require your customers to accept terms & conditions before placing an order, you can use this checkbox. Simply include it on any page of the checkout, like so:

<input type="hidden" name="accept_terms" value="0">
<input type="checkbox" name="accept_terms" value="1" {accept_terms_checked} >

Or more simply:

{field:accept_terms} <label for="accept_terms">I accept the terms & conditions</label>

The hidden field is required and must be placed before the checkbox, because per the html specifications, if a checkbox is unticked then nothing is submitted (and Store wouldn’t be able to tell whether the checkbox existed on your page in the first place).

If you don’t want the checkbox to be automatically checked when customers click the back button, simply template it yourself, without using the {accept_terms_checked} helper.

Billing Details

All billing details are stored in the cart, and you can submit them using standard html inputs.

To display a simple text/drop-down input where appropriate, use the following code:

{field:billing_name}
{field:billing_country}

To customize your inputs, you can simply template them as regular html inputs:

<input type="text" name="billing_name" value="{billing_name}" />

The following fields are available:

billing_name

The billing name.

billing_address1

The first line of the billing address.

billing_address2

The second line of the billing address (usually this field is optional).

billing_address3

The third line of the billing address (usually used for the city).

billing_region

The code of the currently selected region.

billing_region_name

The name of the currently selected region.

billing_region_options

Generates a list of <option> elements to put inside your select tag. For example:

<select name="billing_region">
    {billing_region_options}
</select>

billing_country

The two digit country code.

billing_country_name

The full country name.

billing_country_options

Generates a list of <option> elements to put inside your select tag. For example:

<select name="billing_country">
    {billing_country_options}
</select>

billing_postcode

billing_phone

Shipping Details

All shipping details fields mirror the billing details. You can display and submit them in the same way.

shipping_name

shipping_address1

shipping_address2

shipping_address3

shipping_region

shipping_region_name

shipping_region_options

shipping_country

shipping_country_name

shipping_country_options

shipping_postcode

shipping_phone

Shipping Same As Billing

Most order processes will have a “Shipping same as Billing” checkbox. Using these fields, you can copy the billing details to the shipping details, or vice versa.

To display a simple “Shipping same as Billing” checkbox, use the following code:

<label for="shipping_same_as_billing">
  {field:shipping_same_as_billing} Same as Billing Details
</label>

If you want to customize the checkbox, you can template it yourself:

<label for="shipping_same_as_billing">
  <input type="hidden" name="shipping_same_as_billing" value="0" />
  <input type="checkbox" id="shipping_same_as_billing" name="shipping_same_as_billing" value="1" {shipping_same_as_billing_checked} />
  Same as Billing Details
</label>

The hidden field must be placed before the checkbox, so that if it is unchecked, “0” will be submitted.

Usually you would combine this checkbox with some simple javascript to hide the shipping details when checked:

<h3>Shipping Details</h3>

<label for="shipping_same_as_billing">
  {field:shipping_same_as_billing} Same as Billing Details
</label>

<div id="shipping_details_drawer">
    <!-- shipping details here -->
</div>

<script type="text/javascript">
$(function() {
    // handle the checkbox change event
    $('#shipping_same_as_billing').change(function() {
        if (this.checked) {
            $('#shipping_details_drawer').slideUp();
        } else {
            $('#shipping_details_drawer').slideDown();
        }
    });
    // hide on page load if already checked
    if ($('#shipping_same_as_billing').is(':checked')) {
        $('#shipping_details_drawer').hide();
    }
});
</script>

if shipping_same_as_billing

True if the current cart has the “shipping address same as billing address” option applied.

shipping_same_as_billing_checked

Shorthand for {if shipping_same_as_billing}checked=”checked”{/if}

if billing_same_as_shipping

True if the current cart has the “billing address same as shipping address” option applied.

billing_same_as_shipping_checked

Shorthand for {if billing_same_as_shipping}checked=”checked”{/if}

Shipping Methods

Shipping methods are specified by ID (found in the Store Settings page). You can template the shipping method as a drop-down or hidden fields in your template.

To display a simple shipping method drop-down, use the following code:

{field:shipping_method}

To display a custom shipping method drop-down, simply submit the shipping_method field along with your form:

<select name="shipping_method">
    <option value="">Select shipping method...</option>
    {shipping_method_options}
</select>

shipping_method

The name of the currently selected shipping method.

error:shipping_method

If the shipping plugin returned an error, you can use this variable to display it inline.

shipping_method_id

The ID of the currently selected shipping method.

shipping_method_plugin

The plugin being used for this shipping method.

shipping_method_options

A helper variable to display all available shipping methods as HTML <option> elements.

shipping_methods Variable Pair

Loop through the available shipping methods (useful if you want to display something other than a select menu). Inside the loop, the following variables are available:

  • {method_id} - The shipping method ID.
  • {method_title} - The shipping method title.
  • {method_price} - The price for this shipping method, assuming the current user location. This variable is only available for the Default Shipping Plugin (other shipping plugins which would require a server-side query to display the price).
  • {if method_selected} - True if the current shipping method is selected.

Payment Methods

To give the user a choice between payment methods, you can either use the payment_method="" parameter, or submit a payment_method field on the last page of your checkout.

All payment methods must be configured in the settings. Orders must have a valid payment method before they can be submitted. If payment fails, the customer will be returned to the current page so that they may try again.

For more information about supported payment gateways, and which fields they require, see Payment Gateways.

To display a simple payment method drop-down, use the following code:

{field:payment_method}

To customize your payment method options, simply submit a payment_method parameter with your form:

How would you like to pay for your order?
<label><input type="radio" name="payment_method" value="manual"> Cheque / Bank Deposit</label>
<label><input type="radio" name="payment_method" value="paypal"> Paypal</label>
<label><input type="radio" name="payment_method" value="authorize_net"> Credit Card</label>

<!-- optionally you could use javascript to display a credit card form here when necessary -->

payment_method

Displays the short name of the currently selected payment method. This is useful in conditional statements.

payment_method_name

Displays the full name of the currently selected payment method.

error:payment_method

If the payment gateway returns an error, you can use this variable to display it inline.

Credit Card Details

Some payment gateways require you to submit the credit card details directly, rather than redirecting the user to a secure payment page. For these gateways, you will need to template additional inputs. You will also need to ensure that your web server is correctly set up with an SSL certificate, as credit card details must always be submitted over a secure connection.

All inputs names should be in the format payment[field_name]. For example:

<input type="text" name="payment[card_no]" value="" />

The exact fields required depends on the particular gateway. All gateways require the following fields:

card_no

The credit card number.

card_name

The credit card holder’s name.

exp_month

This should be submitted as 2 digis (e.g. “04”).

exp_year

This should be submitted as 4 digits (e.g. “2011”)

csc

The card security code (also known as the CVC or CVV)

The exp_month and exp_year fields are usually templated as select menus. To help with this, the {exp_month_options} and {exp_year_options} variables are available to you:

<select name="payment[exp_month]">
    <option value=""></option>
    {exp_month_options}
</select>
<select name="payment[exp_year]">
    <option value=""></option>
    {exp_year_options}
</select>

This will automatically generate a list of HTML option elements, based on the current date.

In addition, the PayPal Pro and SagePay Direct gateways require the following fields:

card_type

The card_type field should be templated as a select menu - as a starting point, you could use the following code (delete any cards which your merchant account does not support):

<select name="payment[card_type]">
    <option value="">Select one...</option>
    <option value="visa">Visa</option>
    <option value="mastercard">MasterCard</option>
    <option value="amex">American Express</option>
    <option value="discover">Discover</option>
    <option value="maestro">Maestro (UK)</option>
    <option value="solo">Solo (UK)</option>
</select>

If your merchant supports Maestro or Solo cards, you will also need to template the following fields:

card_issue

The card issue number.

start_month

The card issue month.

start_year

The card issue year.

Tax Rates

Tax Rates are configured under Settings » Tax Rates. The tax rate is decided based on the billing region and country. Only one tax may apply per order.

In general, you can display the tax applicable to any price by appending “_tax” to the variable. You can also display the tax-inclusive price, by appending “_inc_tax”. For example, {price_inc_tax}, {order_subtotal_tax}, and {order_shipping_inc_tax} are all valid variables.

tax_name

The tax name as defined in the Settings.

tax_rate

The tax rate as a decimal (e.g. “0.15”).

tax_percent

The tax rate as a percentage (e.g. “15”).

if tax_shipping

True if the current tax rate is applied to shipping costs.

item_tax

The tax applicable to an individual order item. Must be used inside the {items} loop.

order_subtotal_tax

The tax applicable to your order items.

order_shipping_tax

The tax applicable to your shipping charges.

order_discount_tax

The tax discounted by any promo codes.

order_tax

The total order tax

Promo Codes

To display a simple input for customers to enter a promo code, use the following code:

{field:promo_code}

If you want to customize the input, simply submit a promo_code field with your checkout form:

<input type="text" name="promo_code" value="{promo_code}" />

Only one promo code may be entered per order. To remove promo codes from the cart, you can either submit a blank promo_code field, or use a checkbox or button to submit a remove_promo_code field:

<label>
    <input type="checkbox" name="remove_promo_code" value="1" /> Remove Promo Code
</label>

<input type="submit" name="remove_promo_code" value="Remove Promo Code" />

promo_code

The promo code currently associated with this cart.

promo_code_value

The discount specified for the promo code (either a percentage or absolute value).

promo_code_type

”p” if the promo code is a percentage discount, “v” if the promo code is an absolute value discount.

if promo_code_free_shipping

TRUE if the current promo code triggers free shipping for the order.

order_discount

The total discount applied to this order.

Registering Members

Most stores will allow anonymous orders. However, Store provides a simple way for members to create an account during checkout. To enable member registration, you can either use the register_member="yes" parameter, or submit a the register_member field. To display a register member checkbox field, use the following code:

{field:register_member}

Member accounts will be created based on the order_email, and the email address must not already be used for a member account. After creating the member account, any existing orders tied to that email address will be assigned to the new member.

Member accounts will only be created if a password fields is submitted. In addition, the username and screen_name fields are optional. For example:

{field:register_member} <label for="register_member">Register Member Account?</label>

<!-- These fields are optional -->
<div class="toggle">
  <div>
    <label for="password">Password</label>
    {field:password}
  </div>

  <div>
    <label for="password_confirm">Confirm Password</label>
    {field:password_confirm}
  </div>

  <div>
    <label for="username">Username</label>
    {field:username}
  </div>

  <div>
    <label for="screen_name">Screen Name</label>
    {field:screen_name}
  </div>
</div>

register_member

TRUE if the register member option is enabled for the current cart.

password

This field can be submitted to set a password for the new member account.

password_confirm

This field can be submitted to confirm the customer typed their password correctly.

username

The username for the new member account. This will default to the value of the order_email field, and must be unique.

screen_name

The screen name for the new member account. This will default to the value of the order_email field.

Custom Order Fields

Orders can have up to 9 custom fields associated with them. As with other order fields, you can submit them using the field helper:

{field:order_custom1}

You may also template them as regular form inputs. You can give these fields a custom name under Settings » Order Fields, which will appear on the Order Details page in the control panel.

order_custom1

order_custom2

order_custom3

order_custom4

order_custom5

order_custom6

order_custom7

order_custom8

order_custom9

Inline Error Handling

The following error variables are available when you use the error_handling=”inline” parameter:

error:billing_name

error:billing_address1

error:billing_address2

error:billing_address3

error:billing_region

error:billing_country

error:billing_postcode

error:billing_phone

error:shipping_name

error:shipping_address1

error:shipping_address2

error:shipping_address3

error:shipping_region

error:shipping_country

error:shipping_postcode

error:shipping_phone

error:order_email

error:accept_terms

error:payment_method

error:shipping_method

error:promo_code

error:order_custom1

error:order_custom2

error:order_custom3

error:order_custom4

error:order_custom5

Submitting Orders

Different actions can be taken when your checkout form is submitted, depending on which button the customer clicks. You can have multiple buttons in your checkout form, which each perform different actions.

Update Cart

To update your cart totals, your submit button should be named “update_cart”. In addition, if your submit button name doesn’t match any of the other options below, it will be treated as an update cart button.

{exp:store:checkout}
    <input type="submit" name="update_cart" value="Update Cart" />
{exp:store:checkout}

Next Step

To move to the next step in your checkout, your submit button should be named “next”. For example, the following code will take the user to “checkout/confirm”:

{exp:store:checkout next="checkout/confirm"}
    <input type="submit" name="next" value="Confirm Order" />
{exp:store:checkout}

Previous Step

To move to the previous step of your checkout, you should not use a button, as you do not want to submit and validate the current form. Just use a regular A element instead (which you can style like a button using CSS if you like):

{exp:store:checkout}
    <a href="{path='checkout/cart'}">Back</a>
{exp:store:checkout}

Continue Shopping

On the first page of your checkout, you may wish to have a “Continue Shopping” button, which takes the customer back to the most recent product they were viewing. For this, we provide the {previous_url} variable, which contains a URL linking to the most recent page the user viewed on your site:

{exp:store:checkout}
    <a href="{previous_url}">Continue Shopping</a>
{exp:store:checkout}

Empty Cart

To provide an empty cart function, simply submit your checkout using a button named “empty_cart”:

{exp:store:checkout}
    <input type="submit" name="empty_cart" value="Empty Cart" />
{exp:store:checkout}

Submit Cart

On the final page of your checkout, you want to submit the order. You can do this by naming your button either “submit” or “commit”:

{exp:store:checkout return="order/ORDER_HASH"}
    <input type="submit" name="submit" value="Place Order" />
{exp:store:checkout}

When the cart is submitted on the final page of your checkout, a valid payment method must be specified. If the payment is successful, the customer will be redirected to the URL specified in the return="" parameter. If payment is unsuccessful, the customer will be returned to the final page of your checkout, and the error can be displayed using the {error:payment_method} variable.