DEV Community

Cover image for Title Casing and Ranked Keywords in a Stock Metadata CSV Without the Guesswork

Title Casing and Ranked Keywords in a Stock Metadata CSV Without the Guesswork

I once uploaded 60 vector files to Adobe Stock and got every single one bounced back in under a minute. The CSV was fine to my eyes. The problem was the header row: I had written the columns in an order I thought made sense, and Adobe's ingest checks the header before it checks anything else. Wrong header, instant rejection, no partial credit. That afternoon is why make_metadata.py exists, and it is also why I stopped guessing about title casing and keyword order and wrote rules down instead.

The headers are not negotiable

Each platform has its own fixed column layout, and the script writes exactly what each one demands:

  • Adobe Stock: 5 columns. Filename, Title, Keywords, Category, Releases.
  • Vecteezy: 4 columns. Filename, Title, Keywords, Category.
  • Dreamstime: 15 columns. More fields, same principle.

The rejection is instant and dumb. It does not read your beautiful titles if column two is where column three should be. So the first job of the script is boring: emit the exact header row per platform and nothing else. If you are building your own CSV writer, do this before you think about keywords at all. Get the header byte-for-byte right, test with one file, then batch.

Title casing without a library

Without a titles file, the script falls back to the filename, title-cased. That sounds trivial until you hit the edge cases: sticker-pack-cute-cat becomes "Sticker Pack Cute Cat", which is fine, but svg-icon-for-halloween becomes "Svg Icon For Halloween", which is not, because "Svg" should be "SVG" and "for" should stay lowercase in a natural reading title.

My rules, in order:

  1. Split on hyphens and underscores, since those are the two characters I actually use in filenames.
  2. Capitalize the first word and the last word regardless.
  3. Leave short connectives lowercase in the middle: for, and, with, of, the, a, on, in.
  4. Force uppercase for a small allowlist of acronyms: SVG, PNG, AI, EPS, JPG, PDF, USA, DIY.
  5. Never uppercase a word that is already mixed case like "iPhone", leave it alone.

That is about fifteen lines of Python, no third-party package, and it fixed maybe 90% of my bad titles. The remaining 10% I fix by hand in a titles.json file, which is the honest answer. A filename is a bad title generator, it is only a first pass. The script supports --titles titles.json for exactly this reason: you write real titles once, the script uses them, the fallback only fires when you have not gotten to that batch yet.

Ranked keywords, not random keywords

Here is the part that took me the longest to internalize: keyword order matters. On Adobe Stock, the first ten keywords carry more weight in search ranking than the rest. Most contributors dump 30 to 50 keywords in whatever order they thought of them. That wastes the only ranking lever you fully control.

My rule is simple and mechanical:

  • Keyword 1 is the single most important noun. For a cat sticker, it is "cat", not "cute".
  • Keywords 2 through 10 are the specific, searchable terms. What a buyer would actually type. "cat sticker", "kitten", "pet", in descending order of how a buyer would search.
  • Keywords 11 onward are the long tail. Styles, moods, use cases: "cute", "kawaii", "printable", "sublimation".

I also drop anything that is not true of the image. Keyword stuffing with terms that do not match the asset is the kind of behavior that gets an account reviewed, and a rejected batch costs you a resubmit cycle anyway. Ten honest keywords ranked well beat fifty scattered ones.

The pipeline writes keywords comma-separated into the Keywords column, in that order, from the same titles.json. One file holds both title and keywords per asset, so a batch is one data file plus one command.

The re-run problem

The other failure mode is mine, not the platform's: running the batch twice. Double-posting the same asset is one of the fastest ways to get flagged on any of these platforms. After I did it once, I built upload_tracker.py, a plain-text ledger using nothing but the standard library:

python upload_tracker.py done "asset-001.jpg"
python upload_tracker.py pending items.txt
python upload_tracker.py status
Enter fullscreen mode Exit fullscreen mode

A re-run checks the ledger first and skips anything already marked done. It is not clever, it is just a file that remembers. That is the whole point: the failure it prevents is expensive and the fix is cheap.

Why all of this runs anywhere

None of this needs a GPU or a cloud account. make_metadata.py and upload_tracker.py are pure standard library, so they run on the cheapest box you can rent. My whole pipeline, including the image generation steps, ran on 1 vCPU and 2 GB RAM, one process at a time, with gc.collect() between assets and ru_maxrss checks to see the real memory ceiling. A CSV writer and a ledger fit in a corner of that budget with room to spare.

The parent project behind these scripts is about 19,000 lines and packaged 39 products, roughly 856 MB of finished output, on that hardware. The metadata rules came out of 300+ pages of research into what each platform actually checks, and the scripts encode the parts that matter: exact headers, ranked keywords, no double-posts.

The tool I built from this

Everything above is now packaged as the ai sticker factory playbook, which includes the same four scripts: make_metadata.py for the Adobe 5-col, Vecteezy 4-col and Dreamstime 15-col CSVs, upload_tracker.py for the ledger, plus md2pdf.py and pack_product.py for turning content into a sellable product with a 1280×720 cover and 600×600 thumbnail. The only third-party packages are Pillow and reportlab, and only for those last two scripts.

If you are building your own pipeline, the playbook is the rules and the tools in one place, written from the rejections that taught them. No hype, just what worked.

Get ai sticker factory playbook


Building digital products? Free guides & kits for digital product sellers.

Top comments (0)