Both sides previous revisionPrevious revisionNext revision | Previous revision |
v:2.0:checkout [2017/08/30 22:33] – [Pre-Payment Webhook] marija | v:2.0:checkout [2023/07/19 13:02] (current) – [A Dropdown Example] adam |
---|
One of the major pieces we wanted to simplify and improve upon when we started FoxyCart was the checkout page. In addition to making it a very dynamic one-page checkout, we also revolutionized (big hypey word, we know, but we feel it's true) the way customers choose between a guest checkout or creating an account. | One of the major pieces we wanted to simplify and improve upon when we started FoxyCart was the checkout page. In addition to making it a very dynamic one-page checkout, we also revolutionized (big hypey word, we know, but we feel it's true) the way customers choose between a guest checkout or creating an account. |
| |
No longer will your customers be presented with inputs for their email and password, only to submit the form and be told that they don't have a user, and that if they'd like to register they can click the teeny tiny link in the bottom right. Odds are they don't care about registering; they just want to buy your wares as quickly as possible. Our unique approach automatically determines whether the customer has an account, and also presents easy options to checkout as a guest user if desired (and configured for your store). | No longer will your customers be presented with inputs for their email and password, only to submit the form and be told that they don't have a user, and that if they'd like to register they can click the teeny tiny link in the bottom right. Odds are they don't care about registering; they just want to buy your wares as quickly as possible. Our unique approach automatically determines whether the customer has an account, and also presents easy options within the [[https://admin.foxycart.com/admin.php?ThisAction=TemplateConfig|templates configuration settings]] to checkout as a guest user if desired (and configured for your store). |
| |
The checkout is also highly flexible, and can be modified in a variety of ways. HTML, CSS, and JavaScript are all available for you to perform advanced customizations both of the design and the functionality. | The checkout is also highly flexible, and can be modified in a variety of ways. HTML, CSS, and JavaScript are all available for you to perform advanced customizations both of the design and the functionality. |
<code html> | <code html> |
<div class="fc-form-group "> | <div class="fc-form-group "> |
<div class="col-md-8 col-md-offset-3" data-fc-error-for="referral_source" data-fc-error-class="fc-alert-container--error"> | <div class="col-sm-8 col-sm-offset-3" data-fc-error-for="referral_source" data-fc-error-class="fc-alert-container--error"> |
<div class="fc-input-group-container fc-input-group-container--checkbox fc-input-group-container--active"> | <div class="fc-input-group-container fc-input-group-container--checkbox fc-input-group-container--active"> |
<label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label"> | <label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label"> |
</div> | </div> |
| |
<div class="fc-form-group "> | <div class="fc-form-group"> |
<div class="col-md-8 col-md-offset-3"> | <div class="col-sm-8 col-sm-offset-3"> |
<div class="fc-input-group-container fc-input-group-container--checkbox fc-input-group-container--active"> | <div class="fc-input-group-container fc-input-group-container--textarea fc-input-group-container--active"> |
<label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label"> | <label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label"> |
Order Notes (optional) | Order Notes (optional) |
</label> | </label> |
<div class="fc-form-group"> | <div class="fc-form-group"> |
<textarea name="Order_Notes" id="Order_Notes" aria-required="false" autocomplete="off" class="fc-form-control" placeholder="Questions? Feedback? Let us know!" style="background:#fff; height:5em;">{{ Order_Notes }}</textarea> | <textarea name="Order_Notes" id="Order_Notes" aria-required="false" autocomplete="off" class="fc-form-control" placeholder="Questions? Feedback? Let us know!" style="background:#fff; height:5em;">{{ Order_Notes }}</textarea> |
</div> | </div> |
</div> | </div> |
</div> | </div> |
</div> | </div> |
</code> | </code> |
| |
This code will then be inserted in your checkout page, right under the "almost done" heading on the default checkout template (above the password entry, terms of service, and the main checkout button). Go ahead and load up your checkout to see what you just added. It should look something like this: | This code will then be inserted in your checkout page, right under the "almost done" heading on the default checkout template (above the password entry, terms of service, and the main checkout button). Go ahead and load up your checkout to see what you just added. It should look something like this: |
{{ https://www.evernote.com/shard/s1/sh/1d29183a-c291-4284-9fc0-fdd72dc51a1a/ac39524686564fb6c5a43c60de7b1527/deep/0/Banners-and-Alerts-and-The-Man-Can!-Stuff-Secure-Checkout.png |Thanks to Corganics.com for beta testing 2.0. That's why they're on our screenshots :)}} | {{ https://i.ibb.co/5KLtPvy/foxycheckout.png |Thanks to Corganics.com for beta testing 2.0. That's why they're on our screenshots :)}} |
| |
Note that the HTML we've entered here can be anything at all, but this example is using the same structure as the default template. That way it automatically gets the appropriate styling. | Note that the HTML we've entered here can be anything at all, but this example is using the same structure as the default template. That way it automatically gets the appropriate styling. |
| |
==== A Dropdown Example ==== | ==== A Dropdown Example ==== |
This example uses the sample scenario above, but with a dropdown instead of the text input. Note that you'll see some twig code like this in each option: | This example uses the sample scenario above, but with a dropdown instead of the text input. Note that you'll see some twig code like this at the top of the example code: |
<code> {% if referral_source == "SOURCE_01" %}</code> | <code>{% set options = ["Social Media", "Advertising", "Online Search", "Word Of Mouth", "Other"] %}</code> |
| |
This is what tells the option to retain the value that has already been selected if the checkout page re-renders. | This array sets out what options are present in the dropdown - so can be edited to add or remove options as required. |
| |
<code html> | <code html> |
| {% set options = ["Social Media", "Advertising", "Online Search", "Word Of Mouth", "Other"] %} |
<div class="fc-form-group "> | <div class="fc-form-group "> |
<div class="col-md-8 col-md-offset-3" data-fc-error-for="referral_source" data-fc-error-class="fc-alert-container--error"> | <div class="col-sm-8 col-sm-offset-3" data-fc-error-for="referral_source" data-fc-error-class="fc-alert-container--error"> |
<div class="fc-input-group-container fc-input-group-container--checkbox fc-input-group-container--active"> | <div class="fc-input-group-container fc-input-group-container--checkbox fc-input-group-container--active"> |
<label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label"> | <label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label"> |
<p>How did you hear about us?</p> | <p>How did you hear about us?</p> |
<select name="referral_source" id="referral_source" class="fc-form-control" aria-required="true" data-fc-required> | <select name="referral_source" id="referral_source" class="fc-form-control" aria-required="true" data-fc-required> |
<option value="SOURCE_01" {% if referral_source == "SOURCE_01" %}selected{% endif %}>This Website</option> | <option value="">Please select</option> |
<option value="SOURCE_02" {% if referral_source == "SOURCE_02" %}selected{% endif %}>Online Ad</option> | {% for option in options %} |
<option value="SOURCE_03" {% if referral_source == "SOURCE_03" %}selected{% endif %}>Email</option> | <option value="{{ option }}" {% if referral_source == option %}selected{% endif %}>{{ option }}</option> |
<option value="SOURCE_OTHER" {% if referral_source == "SOURCE_OTHER" %}selected{% endif %}>Other</option> | {% endfor %} |
</select> | </select> |
</div> | </div> |
</div> | </div> |
</div> | </div> |
| </div> |
| </code> |
| |
| ==== A Radio Inputs Example ==== |
| This example uses a similar approach as above, using a line of twig code at the top to set the values of the radio buttons as an array: |
| <code>{% set options = {"Monday": "Monday - First Delivery", "Wednesday": "Wednesday - Second Delivery", "Friday": "Friday - Third Delivery"} %}</code> |
| |
| This array sets out what options are present in the radio inputs - setting both the value for the input ("Monday") and the label shown to the customer ("Monday - First Delivery") - so can be edited to add or remove options as required. |
| |
| <code html> |
| {% set options = {"Monday": "Monday - First Delivery", "Wednesday": "Wednesday - Second Delivery", "Friday": "Friday - Third Delivery"} %} |
| <div class="fc-form-group "> |
| <div class="col-sm-8 col-sm-offset-3" data-fc-error-for="{% for option in options %}Delivery_{{ loop.index }} {% endfor %}" data-fc-error-class="fc-alert-container--error"> |
| <div class="fc-input-group-container fc-input-group-container--checkbox fc-input-group-container--active"> |
| <label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label"> |
| Delivery Day (required) |
| </label> |
| <div class="fc-form-group"> |
| <p>What day would you like to receive your delivery?</p> |
| {% for option, label in options %} |
| <div class="fc-input-group-container--radio"> |
| <label class="fc-form-label" for="Delivery_{{ loop.index }}"><input class="fc-form-control" type="radio" name="Delivery" value="{{ option }}" id="Delivery_{{ loop.index }}" {% if Delivery == option %}checked{% endif %} aria-required="true" data-fc-required /> |
| {{ label }}</label> |
| </div> |
| {% endfor %} |
| </div> |
| </div> |
| </div> |
| </div> |
| </code> |
| |
| ==== A Checkbox Example ==== |
| |
| This is a quick example of a standalone optional checkbox field for the checkout. |
| |
| Special note is that this also includes a hidden input with the same name as the checkbox included just above it in the HTML. This ensures that a value is always passed for the attribute with the transaction. A HTML form only accepts a single instance of a given input name, and a checkbox is only submitted if it's checked. With that in mind - if the checkbox isn't checked, then the hidden input is passed with the transaction. If the checkbox is checked though, then as it's the second input with the same name, it will be the value passed with the transaction. |
| |
| <code html> |
| <div class="fc-form-group"> |
| <div class="col-sm-8 col-sm-offset-3 fc-checkout__additional-field--custom-checkbox"> |
| <div class="fc-input-group-container fc-input-group-container--checkbox"> |
| <label class="fc-input-group-container__title fc-form-label fc-form-label--custom-checkbox"> |
| <input type="hidden" name="my_custom_checkbox" value="0" /> |
| <input type="checkbox" |
| id="my_custom_checkbox" |
| name="my_custom_checkbox" |
| value="1" |
| class="fc-form-control fc-form-control--custom-checkbox" |
| {{ checked(my_custom_checkbox == '1') }} /> |
| My Checkbox Label |
| </label> |
| </div> |
| </div> |
| </div> |
| </code> |
| |
| ==== A Multilingual Example ==== |
| |
| If your store is making use of [[..:template_sets|Template Sets]] to offer [[..:i18n|multilingual]] functionality on your store, you will also want to have your custom checkout fields show in the respective languages too. Here's a quick example of achieving that with the referral field from the first example above. |
| |
| You would obviously need to expand this to match the different languages you offer on your store, as selected in the template sets language dropdown. This example assumes that the default template set uses English, but there are also template sets using German and French. |
| |
| <code html> |
| {% set referral_label = "Referred by... (required)" %} |
| {% set referral_description = "Please let us know who referred you." %} |
| |
| {% if language == "german" %} |
| {% set referral_label = "Empfohlen von... (erforderlich)" %} |
| {% set referral_description = "Bitte teilen Sie uns mit, wer Sie empfohlen hat." %} |
| {% elseif language == "french" %} |
| {% set referral_label = "Référencé par... (obligatoire)" %} |
| {% set referral_description = "Veuillez nous indiquer qui vous a référé." %} |
| {% endif %} |
| |
| <div class="fc-form-group "> |
| <div class="col-sm-8 col-sm-offset-3" data-fc-error-for="referral_source" data-fc-error-class="fc-alert-container--error"> |
| <div class="fc-input-group-container fc-input-group-container--checkbox fc-input-group-container--active"> |
| <label class="fc-input-group-container__title fc-input-group-container__title--forced fc-form-label"> |
| {{ referral_label }} |
| </label> |
| <div class="fc-form-group"> |
| <p>{{ referral_description }}</p> |
| <input type="text" id="referral_source" name="referral_source" placeholder="" autocomplete="off" class="fc-form-control" formnovalidate="" aria-required="true" value="{{ referral_source }}" data-fc-required> |
| </div> |
| </div> |
| </div> |
</div> | </div> |
</code> | </code> |
<!-- Radio --> | <!-- Radio --> |
<input type="radio" name="Delivery" value="Monday" {% if Delivery == "Monday" %}checked{% endif %} /> | <input type="radio" name="Delivery" value="Monday" {% if Delivery == "Monday" %}checked{% endif %} /> |
<input type="radio" name="Delivery" value="Tuesday" {% if Delivery == "Tuesday" %}checked{% endif %} /></code> | <input type="radio" name="Delivery" value="Tuesday" {% if Delivery == "Tuesday" %}checked{% endif %} /> |
| |
If the field you're wanting to maintain is a hidden field (one prepended with ''h:''), then you'll need to access it in a slightly different way using Twig's global ''_context'' object. This is because the colon in the field name changes how it needs to be referenced, as a string rather than an object. If you had a field with a ''name'' of ''h:hidden_field'', you would access it as ''_context['h:hidden_field']'' in Twig. | <!-- Select Dropdown --> |
| {% set options = ["Social Media", "Advertising", "Online Search", "Word Of Mouth", "Other"] %} |
| <select name="referral_source" id="referral_source" class="fc-form-control" aria-required="true" data-fc-required> |
| <option value="">Please select</option> |
| {% for option in options %} |
| <option value="{{ option }}" {% if referral_source == option %}selected{% endif %}>{{ option }}</option> |
| {% endfor %} |
| </select> |
| </code> |
| |
| **If your field name includes accented characters, or if you're setting it up as a hidden field (one prepended with ''h:'')**, then you'll need to access it in a slightly different way using Twig's global ''_context'' object. This is because the colon or accented characters in the field name changes how it needs to be referenced, as a string rather than an object. If you had a field with a ''name'' of ''h:hidden_field'', you would access it as ''_context['h:hidden_field']'' in Twig. |
==== What about Receipts and the Datafeeds? ==== | ==== What about Receipts and the Datafeeds? ==== |
The custom fields will be inserted at the bottom of your receipt (after checkout), as well as in any emails that include receipt placeholder. | The custom fields will be inserted at the bottom of your receipt (after checkout), as well as in any emails that include receipt placeholder. |
| |
==== "Sensitive" Custom Checkout Fields ==== | ==== "Sensitive" Custom Checkout Fields ==== |
By default, all custom checkout fields will be emailed as part of the email receipt sent to both the customer and the store's email address. <wrap important>Emailing sensitive information is a Bad, Bad Idea. If you aren't familiar with the reasons why, please read our [[:primer:security|Security Primer]] for more info.</wrap> If you do need to collect information that you //do not want to be emailed//, such as Social Security Numbers or other sensitive data, you can prefix your field names with ''h:'', like this: | By default, all custom checkout fields will be emailed as part of the email receipt sent to both the customer and the store's email address. <wrap important>Emailing sensitive information is a Bad, Bad Idea. If you aren't familiar with the reasons why, please read our [[:primer:security|Security Primer]] for more info.</wrap> If you do need to collect information that you //do not want to be emailed//, such as account ID numbers or other sensitive data, you can prefix your field names with ''h:'', like this: |
<code html> | <code html> |
Please enter your Social Security Number: <input type="text" name="h:social_security_number" /> | Please enter your Secret Account ID: <input type="text" name="h:secret_account_id" value="{{ _context['h:secret_account_id'] }}" /> |
</code> | </code> |
"Sensitive" fields are displayed in the admin's transaction view, and are sent in the XML, but are not emailed. | "Sensitive" fields are displayed in the admin's transaction view, and are sent in the XML, but are not emailed. |
{% endfor %} | {% endfor %} |
{% endif %}</code> | {% endif %}</code> |
| ==== Passing Custom Fields to the Custom Shipping Code ==== |
| Include a data attribute of ''data-fc-shipping-custom-field'' to capture the information from a customer on the checkout related to the shipping. Review [[https://wiki.foxycart.com/v/2.0/shipping#passing_custom_fields_to_the_custom_shipping_endpoint|this link]] for complete information on custom fields (''fx:custom_fields'') in custom shipping code or endpoint using ''data-fc-shipping-custom-field''. |
===== Pre-Populating the Checkout with Customer Information ===== | ===== Pre-Populating the Checkout with Customer Information ===== |
Though we generally recommend [[.:sso|Single Sign-On]] and synching [[.:customers|customers]] via [[.:api|the API]], there are certain situations where you may want to pre-populate the customer's billing or shipping fields without using SSO or the API. | Though we generally recommend [[.:sso|Single Sign-On]] and synching [[.:customers|customers]] via [[.:api|the API]], there are certain situations where you may want to pre-populate the customer's billing or shipping fields without using SSO or the API. |