← All Work
Malka Media — 2024–2025

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.

1,702
Personalized cards
6,800+
Files rendered
268
Boscov's deliverables mapped
The hard part

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.

Client
Malka Media (internal) · Boscov's
Agency
Malka Media
Role
Animation Director After Effects Pipeline / ExtendScript / Data Design
Timeline
Nov 2024 — 2025
The Problem

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 Build

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.

After EffectsExtendScriptGoogle Sheets → TSVcompsFromSpreadsheetRender Queue scriptingPNG slices · GIF · MOVMonday.com import
Engine one · Malka Holiday Cards

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.

  1. 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.

    MALKA_HolidayCard_MASTERsheet.csv · 1,702 rows · names masked here
    emailTop NameTop LogoClient NameFile Name · Slice_01File Name · Slice_02Slice 03 (GIF)
    •••••@adp.comT•••••ADP.pngT••••• O••••••,MALKA_HolidayCard_ADP_T••••• O••••••_Slice01…_Slice02MALKA_HolidayCard_ADP.gif
    •••••@adp.comE••••ADP.pngE•••• H•••••,MALKA_HolidayCard_ADP_E•••• H•••••_Slice01…_Slice02MALKA_HolidayCard_ADP.gif
    •••••@adp.comB••••ADP.pngB•••• H•••••,MALKA_HolidayCard_ADP_B•••• H•••••_Slice01…_Slice02MALKA_HolidayCard_ADP.gif
    ……EY.png · 312 rows………MALKA_HolidayCard_EY.gif
  2. 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.

    MALKA_HolidayCard_Comps_1-675.tsv · MALKA_HolidayCard_Comps_676-END.tsv
    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
  3. 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.

    MALKA_HolidayCard_alt01 · master comps · {Top Name} {Top Logo} {Client Name}
    Master · art direction A
    Master · art direction B
  4. 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_Comps_to_Render_Queue_First_Frame_PNG_HQ.jsx · RemoveDuplicateRenderQueueItems.jsx
    // 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;
    }
  5. 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.

    GIF · 2 × PNG · MOV per row
    Per recipientFormatUsed for
    Slice 01PNGEmail body, top
    Slice 02PNGEmail body, bottom
    Slice 03GIF, one per clientAnimated email header
    SocialMOVFor anyone who wanted to post it
  6. 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".

    MALKA_HolidayCard_MASTERsheet — updated URLs.csv
    ClientRecipientSlice 03 (GIF)Status
    ADPT••••• O••••••https://drive.google.com/uc?id=1Zqa…dHdNmerged
    ADPE•••• H•••••https://drive.google.com/uc?id=1c8W…kPq2merged
    EY312 recipientshttps://drive.google.com/uc?id=…merged
    Deloitte235 recipientshttps://drive.google.com/uc?id=…merged
The outputsSame comp, different row — the top-volume logos in the sheet
The Hard Parts

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.

Data hygiene beats clever scripts

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.

Project size, memory and the queue

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.

Engine two · Boscov's Content Engine

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.

  1. 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.

    BOSM24001H · :30 broadcast + digital cutdown · Nov 2024
    The :30 holiday spot
  2. 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.

    MASTER-DELIVERABLE-LIST_010752_Boscovs_Content Engine.xlsx · V4 · 268 line items
    LaunchEventRunDeliverables
    Aug 13Back to School Sale2 wk4 × :30 · 8 × :15 YT · 1 × :10 FB
    Aug 27Labor Day Sale1 wk4 × :30 · 8 × :15 YT · 1 × :10 FB
    Sep 17VIP Biggest Home Sale2 wk6 × :30 · 12 × :15 YT · 1 × :10 FB
    Oct 26Grand Opening Sale (new store)1 wk12 × :30 · 24 × :15 YT · 1 × :10 FB
    Nov 27Black Friday Sale1 wk5 × :30 · 10 × :15 YT · 1 × :10 FB
    Dec 3Month Long Holiday Sale4 wk16 × :30 · 32 × :15 YT · 1 × :10 FB
    …11 more events86 × :30 · 168 × :15 · 14 × :10 in total
  3. 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.

    Boscovs_MotionWireframe_01 · 02 · placeholder text is the point
    Wireframe 01 — the beat library
    Wireframe 02 — product slide variants
  4. 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.

    CreativeDesign Tracker · palette · headers · photography · fonts
    Boards — opening
    Boards — product beats
    Boards — endcards
  5. 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.

    Monday_Import_Boscovs_2025.csv · 17 rows → 268 tracked items
    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 2024 pilot, in stagesThe four modules the engine was built to reproduce — hover to play
Module
01 · The box arrives
Module
02 · The reveal
Module
03 · The conveyor of deals
What Carried Over

The rules both engines ran on

Design once, name precisely

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.

Make the failure visible before the render

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.

Scope

Deliverables

1,702 personalized cards6,808 rendered files74 client brands2 master art directionsPNG email slicesAnimated GIFMOVDrive URL write-back17 Boscov’s sales events268 deliverables mappedMotion wireframe system:30 · :15 · :10 formatsMonday.com importExtendScript tooling

Have a Project in Mind?

Animation direction, VFX and creative technology. Message me on LinkedIn or get in touch.