Redesigning AMS Giving
Using VueJS to reskin a legacy ASP.net app for the needs of a modern donation campaign.
At the American Meteorological Society, we wanted to launch a large fundraising campaign alongside our centennial celebration. Here’s how we went about preparing a legacy ASP.net app for the needs of (hopefully) a record amount of giving.
The State of Modern Web Giving
The first stage of the process was to do a survey of what modern giving on the web looks like. Our digital communications team trawled through a wide variety of other nonprofit sites to see what they were offering, how they were offering it, and how different options were presented. Then we looked at a wide range of third-party giving applications to see if we could use something off the shelf instead of recreating it ourselves.
We found that modern giving pages optimize the mobile experience, provide default giving options to anchor the user’s gift amounts, and present sleek, simple user interfaces that respond to user interaction.
Meeting Business Requirements
AMS had a few business requirements that made third-party platforms impractical. We had 17 different funds that users could choose to give to, and we also wanted to allow users to log in with their existing AMS accounts instead of manually supplying addresses and emails. And perhaps most importantly, there was the cost.
Unlike most nonprofits, AMS does not use donations to cover its day-to-day operating expenses (those are covered by other revenue streams). Accordingly, AMS passes on 100% of donations to the specified cause, even subsidizing the transaction fees from credit card donations. Most third-party giving platforms take a small cut of donations on top of the standard transaction fees (usually 3%–5%). For AMS to continue handling donations the way it does, this would mean paying the extra cost out of its operating budget, so getting a record number of donations through one of these third-party apps would present a substantial extra expense.
Reworking the Legacy App
With all of this in mind, we assessed our current app. With a few tweaks, the back end of the app could still work for our purposes: payment processing, donor log in, and fund listings already all worked and were connected to our databases. The main issues were really on the front end.
As such, we set about redesigning the page with the new look and feel we needed, while still connecting to the existing back end logic.
The first hurdle was to create an interface that would be simple and familiar to users, while still giving them the flexibility to designate different amounts to one or more of 17 funds.
The number of funds itself created the main issue: 17 is a lot to present in an elegant manner, and in the previous version of the app, this had felt overwhelming. As we couldn’t whittle this number down, after a few wireframe iterations, we chose to go with a strategy of grouping and filtering, while creating a default “fast lane” for users who don’t want to specify where their money goes.
Choosing the Right Tools
One option for the funds would have been to create distinct visual groupings, separating them out into different boxes on the screen. But we ran into the issue that there is a lot of overlap between any potential groupings.
As such, we needed non-static groupings that could shift and present differently depending on the user’s actions. And that sort of dynamic presentation is a great use case for a JavaScript framework.
From my personal projects, I was very familiar with React, but I also knew that React would not be practical in this case. The ecosystem and particular syntax of React mean that it’s tough to integrate without a dedicated organizational commitment. And, as the front end developer at AMS, I didn’t want to create something that would be confusing for back end developers or web editors in future.
Because of this, I instead turned to VueJS. Vue is very light, it can be included from a CDN with a script tag, it looks like standard HTML and CSS (with a few v- flags included), and though it benefits from Babel and other tooling, it doesn’t require them. And because Vue would abstract out user-entered values into a JS-managed state, it would allow me to create a more responsive user experience in various ways. I spent some time digging through the Vue documentation and working through a couple tutorials and then got to work.
Rebuilding the Front End
Because we were focused on modernizing the existing app, I decided not to build it as a full single-page application, but to make use of the existing HTML form submissions and keep it as three distinct pages. This allowed me to work on a tight timeline, while keeping essentially all the working, well-tested logic in place, including validation on the server side before the final payment submission.
I also used a lot of the CSS I had written for our Boostrap 4-based Centennial site, which made for visual continuity and minimal styling time.
To create the fast lane for fund-ambivalent users, I created a large input and default-payment buttons right at the top of the screen. A “next” button right below this input allows users to click through without ever looking at the funds, if they desire.
For the funds themselves, as they need to be shown or hidden depending on the application of certain filters (controlled by toggled buttons), I took the original array passed from the database and created a computed property that uses the Array.filter method to remove the correct funds.
There was a problem with this approach.
With the funds and the fast lane being treated as visually separate, it wasn’t clear to users that they could actually give to both at the same time (the default input is actually processed as a fund, albeit an unrestricted fund).
To address this issue, I used the state held in Vue to create a shopping cart-like component both at the top of the screen and at the bottom above the “Next” buttons. This allows users to see all the money entered into various funds. And an “X” button nearby allows users to set a particular value in the state (and also, therefore, in the input itself) back to 0 without searching through the whole screen.
Other Vue-based improvements included a prompt (drawn from a computed total) to let users know if they are nearly at the $2019 Centennial Leadership Circle giving amount, hashtag URLs of #circle and #student that automatically populate the value with $2019 or $20.19 (the Student Leadership Circle amount), highlighting of funds that have had values entered, and client-side validation that restricts and properly formats entered amounts.
This all had the benefit of making the form seem far more responsive to user input and gave users feedback of what exactly they had put money into before progressing further.
Log In Page
Because the majority of our donors are also AMS members, and because logging in will save them time entering their information further down the road, I designed the login page to prioritize logging in, while also presenting guest checkout as an option. This page is relatively simple, but the key was to strip away anything beyond what is necessary. At this point, and within the AMS online ecosystem as well, such login pages are familiar to most users and don’t require much explanation.
Checkout Page
Previously, we were collecting a lot of information from users over two different pages, with completely separate forms for contact information and payment information. I combined these pages and stripped away any fields that were not necessary, hiding the billing address inputs until a user specifies that their billing address is different from their contact information.
As our payment processing already determines the card by the starting digit, I replaced a dropdown for Card Type with images of the accepted card types (with titles for accessibility) and minimized explanatory text to only those items that may confuse the user.
Reflections
After all of the design and coding was done, we had multiple rounds of testing, polishing, and bug hunting before launching on August 15th.
Overall, the process of reskinning this app gave us what we needed to be able to launch our Centennial campaign with confidence. And I was really floored by how well Vue fit the needs of the project.
However, this project also provided some valuable learning opportunities, and there are some definite areas for future improvement.
- While there were good reasons behind choosing not to make this a full single-page application, there were enough tradeoffs to developing it that way that, in future, it would be worth taking the dive into fully separating the front and back ends. As it was, this way required far more contact points between the front and back ends, and in future this will make maintainability more work (for example, if we do swap out the ASP.net in future, this will require some changing of the front end code as well). This would also allow us to lean more heavily on the Vue ecosystem, including VueCLI.
- There are still some steps for users that could be stripped away. On the checkout page, we would like to work toward only collecting an email as contact information (with the billing address information being the only address fields). But for the way we currently operate (sending physical letters to all donors), this still makes for a big improvement.
- Further transitions and animations would make everything feel smoother to users. These were largely left out because of time constraints, but we will plan to add these in the next iteration.