Automation at Scale
Two batch-render engines in After Effects — 1,702 personalized holiday cards for Malka's clients, and a content engine that turned Boscov's year of sales into a deliverable matrix
Two batch-render systems built in After Effects: a spreadsheet-driven engine that produced 6,800 personalized holiday-card files for 1,702 recipients across 74 client brands, and a retail content engine that mapped Boscov's 2025 sales calendar into 268 templated deliverables.
Nobody opens a comp 1,702 times. The sheet is the source of truth, the master comp is the only thing a designer touches, and everything between them — comp duplication, text and logo swaps, render-queue population, naming, de-duplication, and the URLs going back into the sheet — is script.
Two briefs, one shape. Malka wanted a holiday card for every person its account teams worked with — not one card per client, one card per recipient, with their first name, their full name and their company’s logo, delivered as email slices, a GIF and a video. Boscov’s wanted a year of retail sales — seventeen events, each with its own :30 variations, YouTube cutdowns and a Facebook cut — from one motion system. Both are “make thousands of nearly identical things, correctly, by a date.”
The same discipline both times: put the variation in a spreadsheet, keep exactly one master composition, and script the distance between them. After Effects does the rendering; ExtendScript does the drudgery — duplicating comps from rows, swapping text and logo layers, loading the render queue with the right output template and filename, and stripping duplicates before an overnight run. The holiday engine went to 1,702 comps and 6,800 files. The Boscov’s engine mapped 268 deliverables onto a wireframed template system with the event, price and product as the only variables.
One comp, 1,702 recipients
Every account lead at Malka got a card for every person they worked with — name on the front, company logo top and bottom, their name again in the sign-off. Here is one row of the sheet followed all the way to the inbox.
-
The sheet is the brief
Account teams filled one Google Sheet: recipient email, first name, company logo file, full name, and the filenames every output should carry. Nine columns, 1,702 rows, 74 logos. Nothing else about the project was allowed to live outside this sheet.
email Top Name Top Logo Client Name File Name · Slice_01 File Name · Slice_02 Slice 03 (GIF) •••••@adp.com T••••• ADP.png T••••• O••••••, MALKA_HolidayCard_ADP_T••••• O••••••_Slice01 …_Slice02 MALKA_HolidayCard_ADP.gif •••••@adp.com E•••• ADP.png E•••• H•••••, MALKA_HolidayCard_ADP_E•••• H•••••_Slice01 …_Slice02 MALKA_HolidayCard_ADP.gif •••••@adp.com B•••• ADP.png B•••• H•••••, MALKA_HolidayCard_ADP_B•••• H•••••_Slice01 …_Slice02 MALKA_HolidayCard_ADP.gif … … EY.png · 312 rows … … … MALKA_HolidayCard_EY.gif -
Split into batches After Effects can survive
A 1,702-comp project is a crash waiting to happen, so the sheet was exported as tab-separated batches — comps 1–675 and 676–end — with a leading column naming the master comp each row should be cloned from. The TSV is the contract between the data and the template.
comps Top Name Top Logo Client Name Bottom Logo File Name MALKA_HolidayCard_alt01 T••••• ADP.png T••••• O••••••, ADP.png MALKA_HolidayCard_ADP_T••••• O•••••• MALKA_HolidayCard_alt01 E•••• ADP.png E•••• H•••••, ADP.png MALKA_HolidayCard_ADP_E•••• H••••• MALKA_HolidayCard_alt01 B•••• ADP.png B•••• H•••••, ADP.png MALKA_HolidayCard_ADP_B•••• H••••• … 674 rows in batch one, 1,030 in batch two -
One master, two art directions
The only thing anyone designed by hand. Text layers and two logo placeholders named exactly as the sheet's columns — Top Name, Top Logo, Client Name — so the comps-from-spreadsheet script could find them. A second art direction shipped as an alternate master; a row could point at either. Shown here with the field names in place of a real recipient.
Master · art direction A Master · art direction B -
Script the render queue, then de-duplicate it
Each duplicated comp needed three renders with three output templates — two PNG email slices from single frames, and the animated GIF and MOV from the full timeline — each named from the sheet. Two small ExtendScript tools did that: one loads every selected comp into the queue as a single-frame PNG-HQ render with the right name, the other walks the queue and removes duplicates before the overnight run.
// Add selected comps to the render queue as a single first frame, PNG-HQ template for (var i = 0; i < selectedItems.length; i++) { var item = selectedItems[i]; if (item instanceof CompItem) { var rq = project.renderQueue.items.add(item); rq.timeSpanStart = 0; rq.timeSpanDuration = item.frameDuration; // one frame var om = rq.outputModule(1); om.file = new File(item.name + "_FirstFrame.png"); om.applyTemplate("PNG - HQ"); } } // Walk the queue; drop any item whose comp + output path was already seen for (var i = 1; i <= renderQueue.numItems; i++) { var it = renderQueue.item(i), key = it.comp.name + it.outputModule(1).file.fsName; if (seen[key]) toRemove.push(it); else seen[key] = true; } -
Render
Four files per recipient: two PNG slices for the email body, a client-level GIF for the animated header, and a MOV for anyone who wanted to post it. 1,702 recipients across 74 logos became 6,808 files, rendered unattended.
Per recipient Format Used for Slice 01 PNG Email body, top Slice 02 PNG Email body, bottom Slice 03 GIF, one per client Animated email header Social MOV For anyone who wanted to post it -
Close the loop back into the sheet
Renders were pushed to Drive and each row got its share URLs written back into the same sheet — so the mail merge read from the document the account teams had filled in the first place. No manual attaching, no renaming, no "which file is T•••••'s".
Client Recipient Slice 03 (GIF) Status ADP T••••• O•••••• https://drive.google.com/uc?id=1Zqa…dHdN merged ADP E•••• H••••• https://drive.google.com/uc?id=1c8W…kPq2 merged EY 312 recipients https://drive.google.com/uc?id=… merged Deloitte 235 recipients https://drive.google.com/uc?id=… merged
Where a batch of 1,702 actually breaks
Rendering is the easy half. These are the things that had to be solved before an overnight run could be trusted.
Trailing commas after names, logos saved as .webp when the template expected .png, the same person appearing under two account leads — every one of these is a broken render at 3am. The sheet went through several passes (a blank-slice variant, a generic fallback card for rows with no logo, a final “updated URLs” version) before the batch was allowed to start. The filename columns were generated in the sheet from the name and logo columns, so a typo in one place produced a wrong filename you could see before rendering, not a mystery file afterwards.
After Effects will not happily hold 1,700 comps in one project, and the render queue will happily hold the same item twice. Batching the TSV into two projects kept each one openable; the single-frame PNG script kept the slice renders from spinning up a full-timeline render per image; the de-duplication script kept re-runs from doubling the queue when a batch had to be restarted. Between them, a restart cost minutes instead of a night.
Seventeen sales, one motion system
After the 2024 holiday spot, Boscov's wanted the whole 2025 calendar produced the same way — every sale event with its own :30 variations, :15 YouTube cutdowns and a :10 for Facebook. The answer was a deliverable matrix and a wireframed template system that treats price, product and event name as data.
-
The 2024 pilot — a spot built from parts
The holiday spot that started it. Gift boxes, a reveal, a conveyor of deals, dates and the outro — cut as four modular stages so the weeks-two-and-three digital versions could swap products and prices without re-animating the frame. It proved the shape before the year-long engine was scoped.
The :30 holiday spot -
Map the year as a matrix
Seventeen events between August and December, each with a launch date, a run length and a deliverable formula. The master list went through four versions as the client's calendar moved; the final one is the production order for the whole engagement — and the import file for the project tracker.
Launch Event Run Deliverables Aug 13 Back to School Sale 2 wk 4 × :30 · 8 × :15 YT · 1 × :10 FB Aug 27 Labor Day Sale 1 wk 4 × :30 · 8 × :15 YT · 1 × :10 FB Sep 17 VIP Biggest Home Sale 2 wk 6 × :30 · 12 × :15 YT · 1 × :10 FB Oct 26 Grand Opening Sale (new store) 1 wk 12 × :30 · 24 × :15 YT · 1 × :10 FB Nov 27 Black Friday Sale 1 wk 5 × :30 · 10 × :15 YT · 1 × :10 FB Dec 3 Month Long Holiday Sale 4 wk 16 × :30 · 32 × :15 YT · 1 × :10 FB … 11 more events 86 × :30 · 168 × :15 · 14 × :10 in total -
Wireframe the motion, not the sale
A motion wireframe built with every retail beat Boscov's would ever need — name of sale, on-model product, centered product, lay-flat, two-image, full-bleed, product slides, website and CTA — each a comp with named placeholders for price, brand and imagery. An event becomes a selection of beats plus a data row; a variation is the same beats with a different row.
Wireframe 01 — the beat library Wireframe 02 — product slide variants -
A style guide per event, as data
Each event carried its own palette, headers, photography and font notes in a design tracker sheet, so the same wireframe could read as Labor Day or Black Friday without anyone re-keying colours. The 2024 boards show the system the wireframe formalised.
Boards — opening
Boards — product beats
Boards — endcards -
Batch the variations, feed the tracker
With the beats wireframed, each event's :30 variations, :15 cutdowns and :10 cut are render-queue items rather than edits. The same deliverable list was reshaped into a Monday.com import so every line had an owner and a due date the moment the client approved the calendar.
Launch Date,Event Name,Duration,Deliverables Overview,External Folder,Color Palette,Headers 2025-08-13,Back to School Sale,2 weeks,"4x -- 30s ad variations / 8x -- 15s YT Cutdowns / 1x -- 10s FB Cutdown",EXT FOLDER | Back to School,, 2025-08-27,Labor Day Sale,1 week,"4x -- 30s ad variations / 8x -- 15s YT Cutdowns / 1x -- 10s FB Cutdown",EXT FOLDER | Labor Day Sale,LABOR DAY PALETTE, 2025-09-17,VIP Biggest Home Sale,2 weeks,"6x -- 30s ad variations / 12x -- 15s YT Cutdowns / 1x -- 10s FB Cutdown",EXT FOLDER | VIP Biggest Home,VIP PALETTE,VIP HEADER … one row per event; each expands into its own line items in the tracker
The rules both engines ran on
Every layer a script needs to touch is named after the column that feeds it. The master comp is the only file with taste in it; everything downstream is deterministic. If a card looks wrong, the fix is in the sheet or the master, never in comp number 1,204.
Filenames generated from data, batches sized for the machine, a queue that refuses duplicates, and a tracker that mirrors the deliverable list. The goal in both projects was the same: the overnight run should be boring, and when it isn’t, the morning should tell you exactly which row to fix.
Deliverables
Have a Project in Mind?
Animation direction, VFX and creative technology. Message me on LinkedIn or get in touch.