Bulk Upload
Problem
Customers are complaining about the slow process of manual campaign creation. Many marketers work from Excel spreadsheets and we are forcing them to do a ton of mindless copy-pasting.
Some background: the Accomplice platform allows you to create many different Facebook ads and launch them together, then redistribute the budget to the best-performing ads.
For reference, these are the fields we're talking about (for Facebook):
Ideally, marketers should be able to upload a ‘.csv’ file with all the required data and it will magically create all the necessary ads. I was responsible for making this dream come true.
This poses a couple of challenges.
1) What kind of crazy stuff do we have to check for in a blank spreadsheet?
2) How does one go about making hundreds of ads when the system is designed for one at a time?
1) Validation
Some of the many validations that are usually done in the process of filling out the form (first 2), or avoided implicitly by the UI (last 3):
- They included every required field
- None of the fields exceed their maximum allowed length
- The image names they cite are already uploaded to the gallery
- The call-to-action is one of the available options based on that channel and ad-type
- They have access to post on behalf of the Facebook page they claim
The idea is that all of the validation is done rather strictly up front, so that when the campaigns are created they are all valid and there aren’t any surprises. This can result in a rather discouraging wall of red text, but with very specific and helpful error messages, the file is easy to fix.
The hard part here is making the validation messages helpful. I decided to include the row number on their spreadsheet with every error so they would be easier to look up. I also listed the available options if I knew it would be a short and finite list.
I had to constantly think about how to be as lenient as possible while allowing for zero ambiguity. For example, "BUY NOW" is an acceptable substitute for Facebook's "Buy Now" call-to-action but "WATCH" could mean "Watch Now" or "Watch Video."
2) All that data
Once you know the data is all valid, if you create 100 valid ads, will they all show up in the right order and not over-write each other? Does the overworked backend team need to write a whole new endpoint?
Well, with the help of JavaScript promises, we can reuse the existing endpoints to serve a supercharged purpose. The promise "chain" can ensure that steps are never taken out of order, even if that means we have to wait for a bit to hear back from the server between some steps.
So the general order of operations is something like:
- Ask the server for the names of the images the user has uploaded
- THEN send those names and some metadata about the campaign to the validation service to check if there are errors. If there are, stop now and show those.
- If everything looks good, set up the JSON for the ads in preparation for sending
- Ask the microservice if the tracking script is installed on their website
- THEN set the status of the tracking script for each ad
- Instantiate the ad
- THEN edit the ad by uploading the JSON we prepared
- THEN (and only then) update the scope so the user sees the changes.
Basically, every step just before a "THEN" is asynchronous and is waiting on the server to respond. Those steps are either native promises (like the Angular $http) or are wrapped to become promises ($q.defer) such that on their resolution they unlock the next step.
If the user has a beautiful .csv, all of that complexity is hidden in a brief loading animation before their ads are loaded exactly as they want them
Conclusion
This was an interesting project to work on because unlike other "frontend" work, there was very little HTML and CSS involved. The whole feature boils down to two new buttons (download sample, and upload CSV) but behind-the-scenes the little JavaScript elves are hard at work parsing, counting, checking, scrubbing, lexing, and shuttling data back and forth.