Recurring Donation Form

This tutorial demonstrates how to build a custom donation form that supports both once-off and recurring monthly donations. You’ll use Oncord’s built-in form components and Commerce system to dynamically handle donation frequency and payment.

1) Enable Required Modules

Before creating the form, make sure the following modules are active:

  1. Navigate to Settings > Features
  2. Under Commerce, activate:
    • Commerce
    • Recurring Sales (Optional Features)

2) Paste the Form Code

You can add the donation form to a new or existing page. In the page editor, click Source in the left panel, then paste the following HTML in the HTML section:

<forms:form id="donation_form" onsubmitredirect="/commerce/order/success/?sale_id=[? $sale_id ?]" contactmode="store" recordsubmissions="true"> <ajax:event id="donation_frequency_ajaxevent" updateregions="donation_frequency_ajaxregion, donation_paymentmethod_ajaxregion" /> <ajax:event id="donation_paymentmethod_ajaxevent" updateregions="donation_paymentmethod_ajaxregion" /> <forms:row type="two_column" label="Choose your donation frequency"> <forms:radiobuttongroup name="donation_frequency" onchangeajax="donation_frequency_ajaxevent"> <forms:radiobutton valuechecked="once" label="One-time donation" value="once" /> <forms:radiobutton valuechecked="monthly" label="Monthly donation" /> </forms:radiobuttongroup> </forms:row> <forms:row type="two_column" label="Select a donation amount"> <forms:radiobuttongroup name="select_amount" onchangeajax="donation_frequency_ajaxevent"> <forms:radiobutton valuechecked="10" label="$10" /> <forms:radiobutton valuechecked="20" label="$20" /> <forms:radiobutton valuechecked="50" label="$50" /> <forms:radiobutton valuechecked="100" label="$100" /> <forms:radiobutton valuechecked="0" label="Other" value="0" /> </forms:radiobuttongroup> </forms:row> <ajax:region id="donation_frequency_ajaxregion"> <forms:row type="two_column" label="Donation Amount"> <logic:if test="$donation_form.getValueForFormItem('select_amount') == 0"> <forms:money id="donation_amount" validations="mandatory" onkeyupajax="donation_paymentmethod_ajaxevent" value="0" valuePrecision="0" /> </logic:if> <logic:else> <forms:money id="donation_amount" validations="mandatory" value="[? $donation_form.getValueForFormItem('select_amount') ?]" valueignore="ajax" valuePrecision="0" /> </logic:else> <logic:if test="$donation_form.getValueForFormItem('donation_frequency') == 'monthly'"> <sub>/mo</sub> </logic:if> </forms:row> </ajax:region> <h4>Donor's Details</h4> <templates:row> <templates:column width="6"> <forms:row label="First Name" type="one_column"> <forms:editbox id="contact_first_name" datacolumn="contact_first_name" /> </forms:row> </templates:column> <templates:column width="6"> <forms:row type="one_column" label="Last Name"><forms:editbox id="contact_last_name" datacolumn="contact_last_name" /></forms:row> </templates:column> </templates:row> <templates:row> <templates:column width="6"> <forms:row type="one_column" label="E-Mail Address"><forms:editbox id="contact_email" datacolumn="contact_email" /></forms:row> </templates:column> <templates:column width="6"> <forms:row type="one_column" label="Phone Number"><forms:editbox id="contact_phone" datacolumn="contact_phone" /></forms:row> </templates:column> </templates:row> <h4>Payment Details</h4> <ajax:region id="donation_paymentmethod_ajaxregion"> <logic:if test="floatval($donation_amount.value) > 0"> <forms:paymentmethod amount="[? $donation_amount.value ?]" producttitle="Donation" completecart="true" recurring="[? ($donation_form.getValueForFormItem('donation_frequency') == 'monthly') ? true : false ?]" recurringamount="[? ($donation_form.getValueForFormItem('donation_frequency') == 'monthly') ? ($donation_amount.value) : null ?]" recurringinterval="month" /> </logic:if> <logic:else> <h4 style="text-align: left;"><span style="color: #e13e27;font-weight: lighter;">Please enter a minimum donation amount above.</span></h4> </logic:else> </ajax:region> </forms:form>

This form will generate a sales invoice with the product title “Donation”. If a user selects Monthly as the frequency, it will also create a Recurring record for that customer.

The code is set to monthly recurring by default. You can change the recurring interval to weekly, yearly, or other supported intervals based on your needs. Read more here.

3) Add Styling

To enhance the layout and improve usability, paste the following into your page’s CSS tab:

.radio-toolbar { .s8-radiobuttongroup { display: flex; justify-content: flex-start; gap: 1rem; .s8-radiobutton-wrapper { position: relative; text-align: center; padding: 0.5rem 1rem; margin-bottom: 5px; label.s8-radiobutton-container { box-sizing: border-box; width: 100%; height: 100%; margin-right: 0; margin-top: 1px; vertical-align: middle; display: inline-block; cursor: pointer; position: absolute; z-index: 1; top: 0; left: 0; input { display: none; &:checked ~ .s8-radiobutton:before { background-color: #970000; } } .s8-radiobutton { border: 0 none; border-radius: 0; background-color: #b8b8b8; &:before { position: absolute; border-radius: 0; border: 0 none; top: 4px; left: 4px; transition: all 0.3s ease-out; width: 100%; height: 100%; content: ""; background-color: #b8b8b8; } } } .s8-radiobutton-label { color: #fff; z-index: 2; position: relative; } } } .s8-radiobuttongroup--horizontal .s8-radiobutton-container { margin-left: 0; } }

After adding the code, make sure to update your HTML form structure:

  • Add class="radio-toolbar" to each forms:row that contains radio buttons.
  • Set the radio button alignment to horizontal by using the layout

For example:

<forms:row class="radio-toolbar" type="two_column" label="Choose your donation frequency"> <forms:radiobuttongroup align="horizontal" name="donation_frequency" onchangeajax="donation_frequency_ajaxevent">


Note: This CSS is designed specifically for Oncord-based forms and works best when the Minimal form style is selected. If you’re using a different form style, the layout or behaviour might not appear as intended. Feel free to adjust or tweak the styles to suit your website’s design.

Final Notes

  • Using the CSS is optional – it’s provided to enhance the look of the form, but you’re free to use your own styling.
  • By default, the form redirects to Oncord’s Sales system page after submission. To send users to a custom thank-you or confirmation page, update the onsubmitredirect="" value with your preferred URL.
  • Avoid changing the form ID or field IDs unless you’re confident with the structure. Modifying these without understanding the logic may cause the form to stop working.
  • Ensure your payment gateway is connected under Commerce > Settings > Payment Gateways before testing the form.