Moving from another platform
A store moving in from PrestaShop, WooCommerce or Shopify often already sells thousands of printed variants, with the artwork and the provider's product ids in its own database. Linking them one product at a time would take weeks. There are two bulk tools for this, and both start with a dry run and can be undone.
- Assign by SKU: a rule that links every variant whose SKU it catches.
- The links CSV: a spreadsheet with one row per SKU, saying who makes it, from which blank, with which print files.
Both write an explicit link on each variant, once. Nothing routes by SKU at the moment of dispatch. That matters for two reasons: checkout needs to know the provider before an order exists, to quote its shipping, and a SKU typo turns up as a line in the dry run on the day you make it, rather than as a failed order a week later.
Both live under KahunaCart → Print on demand → Products → Assign in bulk, with a Bulk runs list beneath them.
Before you begin
- Your catalogue already in KahunaCart, every variant with its SKU. See Importing.
- The providers you need connected.
kahunacart.pod.manageon whoever runs the bulk tools.
Assign by SKU
- Choose the match:
- SKU starts with a prefix, such as
PF-. Compared without case. - SKU number between two numbers, such as 7000 and 7999. The SKU's leading digits are read as a number, so
7001-BLK-Mis 7001.
- SKU starts with a prefix, such as
- Choose the provider and the mode, Synced or Custom.
- Choose where each variant's blank comes from:
- One blank for every variant, for a range that is all the same item.
- Match options within one product: name one catalogue product (Printful's 71 is the Bella + Canvas 3001) and each variant is matched to its colour and size there. For a synced rule, name the provider's product and variants are matched by SKU first and options second.
- Keep each variant's current one, to change the mode or the files without touching the blanks. Variants with no blank are skipped.
- Optionally pick Shared print files already in the store, to put on every variant the rule links. They are stored once on disk, whatever the count.
- Press the button for the dry run. It answers three lists:
- will link, with the blank each variant gets
- will replace, with the current link beside the new one, so nothing already linked is changed without you seeing it
- will skip, with the reason. A SKU that does not start with digits under a range rule is listed here, because a range cannot place it.
- Read it, then run it for real. It is written as one run.
Variants with no SKU at all, and numeric SKUs outside the range, are counted rather than listed. On a store with twenty thousand variants the list would otherwise be the whole store.
The same through the API is POST /kahunacart/pod/links/assign, a dry run unless you pass dry_run: false.
The links CSV
sku,provider,mode,blank,file:front,file:default
7001-BLK-M,printful,custom,4017,https://files.example.com/7001-front.png,
7001-BLK-L,printful,custom,4018,https://files.example.com/7001-front.png,
8101-A3,gelato,custom,<Gelato product UID>,,https://files.example.com/8101.pdf
5001-POSTER,printful,synced,4011000004,,
| Column | What goes in it |
|---|---|
sku |
The variant's SKU in this store. One row per variant. |
provider |
printful or gelato (Printify has no custom mode and refuses rows in either mode). |
mode |
custom or synced. |
blank |
For a custom row, the provider's blank: a Printful catalogue variant id or a Gelato product UID. For a synced row, the provider's synced variant id. |
file:<print area> |
One column per print area, holding the URL of the file to print there, such as file:front. Leave a cell empty for none. Printful's areas are its own names (front, back, sleeve_left, label_inside and the rest). A Gelato poster, card or other flat product has one area, default; Gelato apparel uses front, back, sleeve-left and sleeve-right. |
Import it from Links CSV on the Products tab, or:
bin/plugin kahunacart-print-on-demand links:import links.csv # the dry run
bin/plugin kahunacart-print-on-demand links:import links.csv --commit # write the good rows
The dry run names every bad line by the line number your spreadsheet shows, and why. A row fails on its own, and the good rows still go in. A row fails when:
- its SKU matches no variant, or two
- its SKU is on an earlier line too
- its provider is not connected
- its blank is one the provider does not know
- a file column names a print area the blank does not take
- a file will not download, or is not a PNG, JPEG or PDF
The dry run only reads the first few bytes of each URL. The real run downloads each URL once, however many rows share it, in the background, so two hundred print files are not fetched inside a browser's patience. Files from private or local network addresses are refused.
Export writes the store's current setup in the same format (Export current links, or links:export --provider=printful --output=links.csv). A file URL in an export points at the store's own copy, so exporting and importing straight back changes nothing and downloads nothing. A cell that starts like a spreadsheet formula (=, +, -, @) is written with a single quote in front, and the import takes it off again.
Undo
Every bulk run is listed under Bulk runs, with what it did and the lines a CSV refused. Undo this run (or links:undo <run>) removes the links it wrote, puts back the links it replaced, takes away the print files it added, and puts back any product it left with no links as it was.
An undo is refused, naming the variants, when anything has changed them since: a later run, Made by on the product, an import. Switching a variant on or off for sale does not count as a change.
A worked example
This feature came from a customer moving off PrestaShop. His setup:
- Products designed in Printful's own designer, sold through Printful's PrestaShop plugin.
- His own artwork library: a print file per design, with the provider's product ids kept in his own database.
- SKUs in ranges that decided who made what: 7000 to 7999 printed on Printful tees, 8000 to 8999 on Gelato posters, and a third range at Prodigi.
Here is how that comes across.
- Import the catalogue with KahunaCart's own importer, so every product and variant exists with its SKU.
- Connect Printful and Gelato.
- Export his database as a links CSV, one row per SKU:
- the Printful-designed products as
printful,synced, with each Printful synced variant id inblank - the 7000s as
printful,custom, with the Printful catalogue variant id inblankand the front file's URL infile:front - the 8000s as
gelato,custom, with the Gelato product UID inblankand the poster file infile:default
- the Printful-designed products as
- Run the dry run. Fix the lines it names in the spreadsheet (a typo in a SKU, a blank Printful does not know, a URL that answers 404) and run it again until it is clean.
- Commit it. The files are fetched in the background and the run is listed under Bulk runs.
- The Prodigi range stays as it is for now. Prodigi is planned for a later release; until then those products ship the way they do today.
- Check a few products' Print on demand panels: each variant shows its provider, its blank and its files. Then place a test order across all three kinds and look at the drafts before sending anything.
No blank ids in the database? Use the SKU rule for the 7000s instead: SKU number between 7000 and 7999, Printful, Custom, Match options within one product naming catalogue product 71. The dry run lists every tee with the 3001 blank it gets in its own colour and size. Then upload each design's front file once on its product's panel, where a product-wide file covers every variant.
If any run went wrong, undo it and run it again.