Marketing Asset Management Script
A small internal tool at SnappPay that closed a recurring loop between marketing and engineering. Marketers uploaded banners, engineers spent hours renaming, resizing, and sorting them. I designed (and built) a script that turned a multi-day handoff into a few clicks.
| Year | 2023 |
| Role | Product Designer (writing code) |
| Stack | Python · wxPython · Google Drive API |

The real question
The marketing team uploaded promo banners into shared folders. Engineering then had to download, verify naming, check file format, confirm size limits, and re-sort everything before it could ship. Nothing was broken — it was just slow, error-prone, and demoralizing.
Where the time was going
Inconsistent names
No naming convention meant engineers had to ask "which one is this?" on every drop.
Wrong file formats
JPGs landing in PNG slots silently broke downstream rendering.
Oversized assets
Banners above the size limit caused display issues no one caught until QA.
Manual sorting
Engineers re-folded every batch into the right subdirectories by hand.
Two trade-offs that shaped the fix
How the system works
Naming convention
Defined with marketing: b-{store}-{type}.png — every banner self-describes.
Drive folders by type
In-store, online carousel, category full, half banner — each in its own folder.
Format · size · name
Script checks PNG, under 3 MB, and matches the convention. Bad files surface with a reason.
Auto-routed output
Verified banners land in the correct subfolder by filename prefix. No manual moves.
Source + destination picker
Marketing picks the folders, hits run, sees a list of recently uploaded files.
Inline error log
Errors appear in the UI with the exact file and reason — fixable without engineering help.

The verification logic
The core function — three checks, then a routed move. Small enough to read in one breath.
def verify_and_sort_banners(source_folder, target_folder):
for filename in os.listdir(source_folder):
filepath = os.path.join(source_folder, filename)
if not filename.lower().endswith(".png"):
print(f"Error: Unsupported format: {filename}")
continue
if os.path.getsize(filepath) > 3 * 1024 * 1024:
print(f"Error: File exceeds 3MB: {filename}")
continue
if not filename.startswith("b-") or "-" not in filename:
print(f"Error: Invalid naming: {filename}")
continue
target_subfolder = os.path.join(target_folder, filename.split("-")[1])
os.makedirs(target_subfolder, exist_ok=True)
shutil.move(filepath, os.path.join(target_subfolder, filename))
print(f"Banner verified and moved: {filename}")
The full Phase 2 version added Google Drive download, a wxPython UI, and inline error reporting in the same flow.
Impact
Hours → minutes
What had been a multi-hour engineering chore became a marketing-team self-serve action.
Errors caught upstream
Bad files fail at upload time, not in QA or production.
Marketing operates it
Engineering stops being the bottleneck for a non-engineering problem.
The script is no longer in active use — a proper back-office system eventually replaced it. That's the point: it was an interim tool that bought the company time to build the right one.
Reflection
The interesting part of this project wasn't the Python. It was deciding that the right output for a product designer, in that moment, was a script — not a spec for engineering to build later. The team needed the problem solved, not handed off.
I'd carry forward two things: designers who can ship small internal tools shorten feedback loops nobody else can reach. And the best interim solutions are the ones that don't pretend to be permanent.