
What is Glass Register?
Stripe is awesome for creating donation forms, but there's a gap in what they offer: Glass Register is there to fill the middle ground between Stripe Checkout and coding from scratch against Stripe's API. It's for when you want complete control of the user experience, down to the pixel and millisecond, but don't want to re-invent the wheel of common interactions (e.g. inline feedback), or the backend (e.g. charge processing and a UI for your gift processing department).
Glass Register's philosophy is to provide you with great tools, but get out of your way if you ask it to. For instance, with form warnings (i.e. after the donor has tried to submit the form with bad/incomplete fields), you can use the built-in functionality that adds classes to your warning HTML elements, or you can register a callback that tells you which fields are invalid and handle it yourself, or any combination of the two.
It also works with your existing web dev workflow. Create your form however you like, put two <script> tags in your page head section, and then add data-* attributes to your input elements which describe what behaviour you'd like from them (e.g. which validator to use). The rest of the configuration is either via Javascript (mostly by registering callbacks for events), or the dashboard.
Glass Register provides:
Charge processing backend
- Processing of the Stripe transaction, including extensive error handling
- Fraud detection with geo-specific policies, as well as the ability to create false-positives in response
- Recording of the form data to highly durable storage
Dashboard
- Configuration panels for non-technical admins (e.g. setting the name which will be put on donor's credit card statement)
- A transaction download area for gift processors: choice of CSV or XLSX, the ability to remove/rearrange the spreadsheet columns
- A panel for having non-technical staff easily enter structured data which then becomes available to the checkout Javascript. This allows the fundraising staff to configure minor aspects of the checkout without requiring a developer each time. The structure of the data is completely configurable by the developer
- A place for developers to create custom connectors to arbitrary REST APIs (e.g. MailChimp, SendGrid, ITTT)
- Queryable event logs, and configuration of triggers for developer notification emails based on those events
Javascript library
- A default set of field parsers, and the ability to register your own
- A default set of field validators, and the ability to register your own
- Inline feedback for donors as they complete fields
- The display of warnings based on form validation, including page scrolling to the first field affected
- Callbacks that let you add code at all the stages of process:
- Just after field parsing and validation (with the ability to make edits to the outcomes of both)
- Just after form warnings have been displayed
- After the form data is validated and just before the charge is made
- On charge success
- On charge failure
- Useful functions (e.g. parsing and displaying currency)
- Country-specific functions and services (e.g. address completion based on Canadian postal codes)
Here's a skeleton example of the source code for a checkout built using Glass Register (visual aspects like labels and styling omitted):
checkout.html
<!DOCTYPE html> <html> <head> <!-- The following two tags enable Stripe and pull in the Glass Register library code --> <script src="https://js.stripe.com/v2/"></script> <script src="http://api.glassregister.io/apps/donate?op=js&clientId=sample&version=1"></script> <!-- This is the code for this checkout - see the next section --> <script src="checkout.js"></script> </head> <body> <!-- The input fields --> <input data-field="_amount" data-parse="amountToCents" data-validate="amount"><br> <input data-field="_ccNum" data-parse="ccNum" data-validate="ccNum"><br> <input data-field="_ccExp" data-parse="ccExpiry" data-validate="ccExpiry"><br> <input data-field="_ccCvc" data-parse="ccCvc" data-validate="ccCvc"><br> <input data-field="_firstName"></br> <!-- Inline feedback. Once input focus has left the field, the function referenced in "data-validate" gets called with the value, and either the "gr-invalid" or "gr-valid" class gets added to this div --> <div class="feedback" data-feedback-for="_ccNum,_ccExp,_ccCvc"> </div><br> <!-- Here's a barebones example of how to style a feedback element --> <style> .feedback.gr-valid { background-color: green; } .feedback.gr-invalid { background-color: red; } </style> <!-- Form errors. Once the donate button has been pressed, all the fields are validated and the "gr-warning" class is added to those warnings that fail validation. Once the field has been edited in any way the class is removed --> <div class="warning" data-warning-for="_amount">[Error text]</div><br> <div class="warning" data-warning-for="_ccNum">[Error text]</div><br> <div class="warning" data-warning-for="_ccExp">[Error text]</div><br> <div class="warning" data-warning-for="_ccCvc">[Error text]</div><br> <!-- Here's a barebones example of how to style a the warning elements --> <style> .warning { display: none; } .warning.gr-warning { display: block; } </style> <!-- The donate button --> <button id="donate">Donate</button> </body>
checkout.js
// Ready: initializes the Glass Register Javascript code, and adds // an event handler for when the donor clicks the donate button $(function() { var donateFn = grInit({ frequency: 'oneTime', preCharge: preChargeFn, chargeError: chargeErrorFn, chargeSuccess: chargeSuccessFn, }); $('#donate').on('click', donateFn); }); // Called just before the form data gets sent to the Glass Register // servers for transaction processing function preChargeFn(form, valids) { // Disable the donate button while we're processing $('#donate').disable(); } // Called when there's some kind of error function chargeErrorFn(result) { if (result.err == 'card-error') { // If it's a card error, let them try again alert('Please check your credit card information!'); $('#donate').enable(); } else { // If it's a big error (e.g. network connection failed) $('body').html(result.msg); } } // Called on successful donation function chargeSuccessFn(form) { $('body').html('Thank you for your donation ' + form._firstName + '!'); }