The majority of cancellations come from customers feeling overstocked, or having too much product. Many customers don't realize that they can skip their upcoming order and instead end up canceling their subscription. To help retain customers on behalf of our merchants, Ordergroove introduced a cancel flow feature within the Subscription Manager to help nudge customers to consider skipping their upcoming order.
How does cancel flow work?
If a customer selects Skip Next Delivery, the next immediate order will be skipped and the following order will ship according to their subscription frequency. For example: on April 15th, a customer clicks ‘skip order’ for their order arriving April 22nd, and their frequency is 1 month, the next order would arrive only on May 22nd.)
How can I get cancel flow for my customers?
You probably already have it! If you have not updated the templates of your Subscription Manager, your customers are already being presented with the cancel flow functionality.
However, if you have updated your Subscription Manager templates (i.e. clicked save on the Subscription Manager page at least once), and still want the new cancel flow feature within your Subscription Manager, you can either create a new theme or make manual code changes to your existing theme to enable it. Take a look below to understand how to update your personalized Subscription Manager templates.
Update liquid templates
A quick note before we start: if you have any customizations in “cancel-subscription.liquid”, you will need to re-apply them after making the update, or integrate them as you go along. The changes will likely go in the new “cancel-subscription-select-reasons” file, which we’ll create later in this article.
In addition, all the changes in this article are required for the functionality to work properly. Because of that, wait to save the changes until you have made all the updates.
In the list of files, scroll down to “Views” and select “cancel-subscription.liquid”. Find the line with the “<dialog” text on it, which represents the start of the cancellation dialog. Then find the line with the “</dialog>” text, which represents the end of the dialog. Replace the content of those lines with the following template:
<dialog aria-hidden="true" class="og-dialog-size"> <form action="{{ 'cancel_subscription' | action }}" name="og_subscription_cancel" @success={{ 'reset_cancel_divs' | js }} @reset={{ 'reset_cancel_divs' | js }} > <input type="hidden" value="{{ subscription.public_id }}" name="subscription" /> {% include 'cancel-subscription-skip' %} {% include 'cancel-subscription-select-reasons' %} </form </dialog>
|
This template includes two additional templates: “cancel-subscription-skip”, which is the content for the initial “skip” dialog, and “cancel-subscription-select-reasons”, which lets the user select a reason for their subscription cancellation. Let’s add those next. Click “Add new file” at the end of the “Views” section in the sidebar. Enter “cancel-subscription-skip” as the name. Paste the following content into the file:
<div class="og-cancel-subscription-skip"> <div class="og-dialog-header"> <h5 class="og-dialog-title og-cancel-title">{{ 'modal_cancel_header' | t }}</h5> <button class="og-button" type="reset" aria-label="{{ 'modal_close' | t }}">{{ 'modal_close' | t }}</button> </div>{# /og-dialog-header #}
<div class="og-dialog-body"> {{ 'modal_cancel_skip_text' | t }}
<div class="og-dialog-stacked-buttons"> <button class="og-button og-emphasis-button" name="skip_subscription" type="button" @click={{ '(ev) => do_skip_next_delivery(ev, order.public_id, order_item.public_id)' | js }}> {{ 'modal_cancel_skip_button' | t }} </button> <button class="og-button" name="continue_cancel_subscription" type="button" @click={{ 'show_cancel_reasons' | js }}> {{ 'modal_cancel_save' | t }} </button>
</div>{# /og-dialog-stacked-buttons #} </div> </div>
|
Next, click “Add new file” again and enter “cancel-subscription-select-reasons” as the name. Paste the following content into the file:
<div class="og-cancel-subscription-select-reasons" hidden> {% set cancel_reasons = 'cancel_reasons' | t %}
<div class="og-dialog-header"> <h5 class="og-dialog-title og-cancel-title">{{ 'modal_cancel_header' | t }}</h5> <button class="og-button" type="reset" aria-label="{{ 'modal_close' | t }}">{{ 'modal_close' | t }}</button> </div>{# /og-dialog-header #}
<div class="og-dialog-body radio-list"> {{ 'modal_cancel_body' | t }}
{% for reason in cancel_reasons | entries | shuffle %} {% set code = reason | first %} {% set text = reason | last %}
{% if code != '1' %} <div class="og-input-group"> <input class="og-check-radio" required type="radio" name="cancel_reason" value="{{ code }} | {{ text }}" id="cancel_reason_{{ code }}_{{ subscription.public_id }}"/> <label class="og-check-radio-label" for="cancel_reason_{{ code }}_{{ subscription.public_id }}"> {{ text }} </label> </div> {% endif %} {% endfor %}
{# Other cancel reason #} {% set other_reason = cancel_reasons | get('1') %} {% if other_reason %} <div class="og-input-group"> <input class="og-check-radio" required type="radio" name="cancel_reason" value="1" id="cancel_reason_1_{{ subscription.public_id }}"/> <label class="og-check-radio-label" for="cancel_reason_1_{{ subscription.public_id }}">{{ other_reason }}</label> </div> <textarea onfocus='this.form.querySelector("input[value=\\"1\\"]").click()' class="og-form-control" name="cancel_reason_details" ></textarea> {% endif %}
<input type="hidden" name="subscription" value="{{ subscription.public_id }}"/>
<div class="og-dialog-stacked-buttons"> <button class="og-button og-emphasis-button" name="skip_subscription" type="button" @click={{ '(ev) => do_skip_next_delivery(ev, order.public_id, order_item.public_id)' | js }}> {{ 'modal_cancel_skip_button' | t }} </button> <button class="og-button" name="cancel_subscription" type="submit"> {{ 'modal_cancel_save' | t }} </button> </div>{# /og-dialog-stacked-buttons #} </div>{# /og-dialog-body #}
</div>
|
Update styles
The new templates require some additional styling. Scroll to the “Styles” section in the list of files and select the “dialogs.less” file. Add the following to the end of the file:
.og-cancel-title { font-size: 20px; }
.og-dialog-stacked-buttons { display: flex; flex-direction: column; align-items: stretch; gap: 15px; margin-top: 20px; max-width: 50%;
button { padding: 16px; }
.og-emphasis-button { background-color: black; color: white; } }
.og-dialog-size { max-width: 700px; }
|
Update scripts
The new templates require some additional scripting. Scroll to the “Scripts” section in the list of files and select the “script.js” file.
First, find the text “function show_closest_modal(ev) {“. A few lines past that, there should be a closing bracket “}”. Replace that section of code with the following:
function show_closest_modal(ev) { const dialog = ev.target.parentNode.querySelector('dialog'); show_and_append_modal(dialog); }
|
Then, add the following lines to the end of the file:
function show_and_append_modal(dialog) { dialog.showModal(); dialog.appendChild(toastsContainer); }
function reset_cancel_divs(ev) { close_closest_modal(ev); const dialog = ev.target.closest('dialog'); const divSkipOrder = dialog.querySelector('.og-cancel-subscription-skip'); const divCancelReasons = dialog.querySelector('.og-cancel-subscription-select-reasons'); divSkipOrder.hidden = false; divCancelReasons.hidden = true; }
function show_cancel_reasons(ev) { const dialog = ev.target.closest('dialog'); const divSkipOrder = dialog.querySelector('.og-cancel-subscription-skip'); divSkipOrder.hidden = true; const divCancelReasons = dialog.querySelector('.og-cancel-subscription-select-reasons'); divCancelReasons.hidden = false; }
async function do_skip_next_delivery(ev, order_id, order_item_id) { reset_cancel_divs(ev); if (window.og.smi.store.getState().items_by_order[order_id].length > 1) { await window.og.smi.api.request_delete_item(order_item_id); } else { await window.og.smi.api.request_skip_order(order_id); } }
|
Update locale files
Finally, we need to update the locale files with the new cancellation text. We need to add some lines and modify some lines. Scroll to the “Locales” section in the list of files and select the “en-US.json” file. Underneath the line that starts with “modal_cancel_save”, add the following lines. If that line does not exist, you can add them anywhere in the top level of the JSON object (i.e., below any line that is indented two spaces).
"modal_cancel_skip_text": "Are you sure? This will cancel all future orders. You can also skip this order and have it sent on a different date and/or frequency that works best for you.", "modal_cancel_skip_button": "Skip Next Delivery",
|
Find the line that starts with “modal_cancel_body” and update it to the following. If the line does not exist, add it the same way you added the previous lines:
"modal_cancel_body": "Please share the reason you are cancelling your subscription.",
|
Find the line that starts with “modal_cancel_header” and update it to the following. If the line does not exist, add it the same way you added the previous lines:
"modal_cancel_header": "Cancel Subscription",
|
You can edit the text of these lines as desired (everything after the “:”), but do not edit the key (e.g. “modal_cancel_skip_text”) unless you also know how to update the template.
You will need to make similar updates to your other locale files. Sample content for the default locales is below. As above, if you already have a line starting with the same key (e.g. “modal_cancel_body”), update that line with the new content instead of adding a duplicate line. If you support other languages, you will need to make similar updates to those files.
en-CA.json
"modal_cancel_body": "Please share the reason you are cancelling your subscription.", "modal_cancel_header": "Cancel Subscription", "modal_cancel_skip_text": "Are you sure? This will cancel all future orders. You can also skip this order and have it sent on a different date and/or frequency that works best for you.", "modal_cancel_skip_button": "Skip Next Delivery",
|
es-ES.json
"modal_cancel_body": "Detalle el motivo por el que cancela su suscripción.", "modal_cancel_header": "Cancelar suscripción", "modal_cancel_skip_text": "¿Está seguro? Esto cancelará todos los envíos futuros. También puede omitir este envío y enviarlo en una fecha y/o frecuencia diferente que mejor le convenga.", "modal_cancel_skip_button": "Omitir próximo envío",
|
fr-CA.json
"modal_cancel_body": "Veuillez partager la raison pour laquelle vous annulez votre abonnement.", "modal_cancel_header": "Annuler l'abonnement", "modal_cancel_skip_text": "Êtes-vous sûr? Cela annulera toutes les commandes futures. Vous pouvez également ignorer cette commande et la faire envoyer à la date et/ou fréquence qui vous conviennent le mieux.", "modal_cancel_skip_button": "Ignorer la prochaine livraison",
|
Wrapping up
With these changes, you should now have the subscription management cancel flow functionality added to your templates. You can test the behavior out by selecting “Basic Editor” in the sidebar and interacting with the displayed demo page. Once you’re satisfied with your changes, make sure to save by clicking the button in the top right of the screen.