Case study · design narrative Case study · narrativa de diseño

How I designed the Etsy Bookkeeping Toolkit Cómo diseñé el Etsy Bookkeeping Toolkit

A design narrative: the four journal entries, the reconciliation layer, the trade-offs behind every decision — and what I’d build next. Una narrativa de diseño: los cuatro asientos contables, la capa de reconciliación, los trade-offs detrás de cada decisión — y lo que construiría después.

Author: Autora: Leslie Nicol Villanueva Published: Publicado: May 2026 Read time: Tiempo de lectura: ~7 min

The problem I wanted to solve

Etsy charges sellers six different kinds of fees per sale: transaction fee, payment processing, listing fees, Etsy Ads, Offsite Ads, and a regulatory operating fee — plus an Etsy Plus subscription if you have one, and a flat fee per shipping label bought on platform.

Most sellers see the deposit hit the bank, glance at the order count, and assume things are fine. After fees, refunds, ads, and shipping, what they actually keep can be 30–40% lower than gross. That gap matters — especially for a maker pricing handmade products against tight margins.

The existing options are manual spreadsheets (brittle, no audit-ready output) or paid bookkeeping platforms (great if you have a monthly subscription and a CPA, overkill for a side hustle). I wanted a third option: an open-access framework that decodes what Etsy is actually charging, in proper accounting language — audit-ready output, no monthly fee. So I built one.

El problema que quería resolver

Etsy le cobra a los vendedores seis tipos distintos de fees por venta: transaction fee, payment processing, listing fees, Etsy Ads, Offsite Ads y regulatory operating fee — más la suscripción Etsy Plus si la tienes y un cobro plano por cada etiqueta de envío comprada en plataforma.

La mayoría de sellers ven el depósito llegar al banco, miran el conteo de órdenes y asumen que todo bien. Después de fees, refunds, ads y envío, lo que realmente se quedan puede ser 30–40% menos que el bruto. Esa brecha importa — especialmente para un maker con márgenes apretados.

Las opciones existentes son spreadsheets manuales (frágiles, sin output auditable) o plataformas pagas de bookkeeping (geniales con una suscripción mensual y un CPA, overkill para un side hustle). Quería una tercera opción: un framework de acceso abierto que decodifique qué te está cobrando Etsy de verdad, en lenguaje contable apropiado — output audit-ready, sin cuota mensual. Así que construí uno.

Why the tool evolved: from Airtable to the browser

The first version was built in Airtable. The accounting framework — 4 journal entry types, fee-category mapping, period-level reconciliation — was fully designed and working. But every time I tested it with a real seller scenario, the same friction appeared: Airtable requires an account, a workspace, and a manual import process that non-accountants find intimidating. The tool was solving the accounting problem but creating a UX one.

The decision to rebuild as a browser tool wasn’t about replacing the framework — it was about removing every step that stood between the seller and their numbers. Upload a CSV, click a button, download an Excel. No account, no install, no import mapping. The accounting logic is identical; the delivery is just radically simpler.

A full accounting platform would be the “professional” choice, but the monthly cost adds up, the learning curve is steep for non-accountants, and Etsy-specific integrations tend to be clunky. Wrong tool for this audience.

Por qué evolucionó la herramienta: de Airtable al browser

La primera versión fue construida en Airtable. El framework contable — 4 tipos de asientos, mapeo de categorías de fees, reconciliación por período — estaba completamente diseñado y funcionando. Pero cada vez que lo probaba con un escenario real de seller, aparecía la misma fricción: Airtable requiere una cuenta, un workspace y un proceso de import manual que intimida a no-contadores. La herramienta resolvía el problema contable pero creaba uno de UX.

La decisión de reconstruirlo como herramienta de browser no fue reemplazar el framework — fue eliminar cada paso que se interponía entre el seller y sus números. Sube un CSV, click, descarga un Excel. Sin cuenta, sin instalación, sin mapeo de import. La lógica contable es idéntica; la entrega es simplemente mucho más directa.

Una plataforma contable completa sería la opción “profesional”, pero el costo mensual se acumula, la curva de aprendizaje es alta para no-contadores, y las integraciones específicas con Etsy tienden a ser torpes. Herramienta equivocada para esta audiencia.

The 4-journal-entries framework

The core decision was breaking each Etsy sale into three per-sale journal entries plus one period-level closing entry. That isn’t how Etsy presents the data — their CSV is a flat ledger of events — but it’s how proper accrual accounting works.

JE 1 — Sale Recognition. Dr Etsy Receivable / Cr Revenue. Etsy is holding the money and will eventually deposit a net amount, so the seller has a receivable, not cash.

JE 2 — Fees & Shipping Booked. Dr Transaction Fee + Dr Payment Processing + Dr Marketing Expense + Dr Shipping Expense / Cr Etsy Receivable. Each cost hits its own expense account; the receivable shrinks by what Etsy is deducting from the payout.

JE 3 — Cash Received. Dr Cash / Cr Etsy Receivable. Closes out the receivable when Etsy deposits the net.

JE 4 — Monthly Closing. The one I almost missed. Etsy also charges things that aren’t tied to a specific sale — the Etsy Plus subscription, listing auto-renewals, regulatory operating fees. These can’t go through JE 2 (per-sale), so they need their own period-level entry: Dr Subscription + Dr Listing Fee + Dr Regulatory Operating Fee / Cr Etsy Receivable. Without it, the receivable account never zeros out.

To map Etsy’s messy CSV onto these clean accounts, each row gets an Accounting Bucket field driven by a nested IF() formula on Etsy’s Type and Title columns. Neither column alone disambiguates — Type=Fee could mean a per-sale transaction fee or a monthly subscription — so the formula looks at Type first and then drills into Title for the gnarly cases. Getting that mapping right is what makes the rest of the toolkit work.

El framework de los 4 asientos contables

La decisión central fue dividir cada venta de Etsy en tres asientos por venta más un asiento de cierre a nivel de período. Así no presenta Etsy la data — su CSV es un libro mayor plano de eventos — pero es cómo funciona la contabilidad de devengo.

JE 1 — Reconocimiento de Venta. Dr Etsy por Cobrar / Cr Ingresos. Etsy retiene el dinero y eventualmente deposita un neto, así que el seller tiene cuenta por cobrar, no efectivo.

JE 2 — Registro de Fees y Shipping. Dr Transaction Fee + Dr Payment Processing + Dr Marketing Expense + Dr Shipping Expense / Cr Etsy por Cobrar. Cada costo va a su cuenta de gasto; la cuenta por cobrar baja por lo que Etsy descuenta del payout.

JE 3 — Efectivo Recibido. Dr Caja / Cr Etsy por Cobrar. Cierra la cuenta por cobrar cuando Etsy deposita el neto.

JE 4 — Cierre Mensual. El que casi me perdí. Etsy también cobra cosas que no van atadas a una venta específica — Etsy Plus, auto-renovaciones de listings, regulatory operating fees. No pueden ir por JE 2 (por venta), así que necesitan su asiento a nivel de período: Dr Subscription + Dr Listing Fee + Dr Regulatory Operating Fee / Cr Etsy por Cobrar. Sin él, la cuenta por cobrar nunca cuadra a cero.

Para mapear el CSV caótico de Etsy a esas cuentas limpias, cada fila recibe un campo Accounting Bucket con una fórmula anidada de IF() sobre las columnas Type y Title de Etsy. Ninguna columna sola desambigua — Type=Fee puede ser transaction fee o suscripción mensual — así que la fórmula mira primero Type y después busca dentro de Title para los casos complicados. Acertar ese mapeo es lo que hace funcionar al resto del toolkit.

The shipping trap most sellers fall into

Etsy supports three shipping setups (customer pays, free shipping seller-absorbs, free shipping with minimum order), but here’s the trap: regardless of which setup you chose, the seller always pays the carrier. The question isn’t “does the seller pay?” — it’s “did the customer reimburse them?”

So the toolkit splits shipping into two fields: Shipping (what the customer paid, from CSV) and Shipping Cost Paid (what the seller paid the carrier). A single formula reveals the truth: Shipping Margin = Shipping − Shipping Cost Paid. Positive means the seller is making money on shipping. Negative means they’re subsidizing it.

If you offer free shipping and your real cost is $4 per order, you’re losing $4 silently on every sale — $200 a month at 50 orders. Most sellers I’ve talked to have no idea this is happening. Etsy strongly encourages free shipping (better conversion and ranking), but the toolkit doesn’t tell sellers what to do — it just makes the actual cost visible so they can decide with eyes open.

La trampa de shipping donde caen la mayoría de sellers

Etsy soporta tres setups de shipping (cliente paga, free shipping con seller absorbiendo, free shipping con minimum order), pero la trampa es: sin importar qué setup eligió, el seller siempre le paga al carrier. La pregunta no es “¿el seller paga?” — es “¿el customer le reembolsó?”

El toolkit divide el shipping en dos campos: Shipping (lo que pagó el cliente, del CSV) y Shipping Cost Paid (lo que el seller pagó al carrier). Una sola fórmula revela la verdad: Shipping Margin = Shipping − Shipping Cost Paid. Positivo = el seller gana plata en shipping. Negativo = lo está subsidiando.

Si ofreces free shipping y tu costo real es $4 por orden, estás perdiendo $4 en silencio en cada venta — $200 al mes con 50 órdenes. La mayoría de sellers no tienen idea. Etsy promueve fuertemente el free shipping (mejora conversion y ranking), pero el toolkit no le dice al seller qué hacer — solo hace visible el costo real para que decida con los ojos abiertos.

The CSV Cleaner — an unexpected friction point

The first time I tested the initial Airtable version with a real CSV, the import failed with a generic “Can’t import CSV file.” The file had three formatting quirks Etsy includes silently: a UTF-8 BOM at file start, the literal string -- as placeholder in empty numeric cells, and currency symbols inside numeric values (-$2.00 instead of -2.00). Three small things, but together they make the toolkit unusable for a typical seller.

Rather than patch Airtable’s import, I built a browser-based CSV Cleaner. The accounting principle of preserving source data isn’t about never touching files — it’s about preserving the audit trail. The original CSV stays in the user’s archive untouched; the cleaner produces a normalized derivative, the same way paid bookkeeping platforms do silently behind the scenes. A transparency panel shows exactly what changed (how many rows processed, how many -- replaced, whether a BOM was stripped). This was the first step toward the full browser tool — once the core logic was running cleanly in JavaScript, the natural next move was to eliminate the import step entirely.

Going further — from cleaner to full report generator

An honest tester pointed out the gap: “If I still have to manually consolidate 4–7 CSV rows per order, this is more complex than a pivot table in Excel.” Fair. The browser report generator solves this completely: upload one CSV, get back a full Excel with P&L Statement and General Ledger. The consolidation, fee netting, journal entry mapping, and balance verification all happen automatically. What used to take an hour now takes under a minute.

Three fields stay deliberately blank: Ad Cost (Etsy bills daily by click-through, not per-order — attributing would mean inventing data), Shipping Cost Paid (label rows show label number, not Order #, so matching is unreliable), and COGS (never in the CSV; must be entered per Listing). Better to leave empty with an honest reason than fill with an estimate that misleads.

El CSV Cleaner — un punto de fricción inesperado

La primera vez que testé la versión inicial en Airtable con un CSV real, el import falló con un “Can’t import CSV file.” El archivo tenía tres detalles de formato que Etsy incluye silenciosamente: un BOM UTF-8 al inicio, el string literal -- como placeholder en celdas numéricas vacías, y símbolos de moneda dentro de valores numéricos (-$2.00 en vez de -2.00). Cosas chicas, pero juntas hacen el toolkit inusable para un seller típico.

En vez de parchar el import de Airtable, construí un CSV Cleaner en el browser. El principio contable de preservar el documento fuente no es nunca tocar archivos — es preservar el audit trail. El CSV original queda intacto en el archivo del usuario; el cleaner produce un derivado normalizado, igual que las plataformas pagas lo hacen silenciosamente. Un panel de transparencia muestra exactamente qué cambió. Este fue el primer paso hacia la herramienta browser completa — una vez que la lógica central corría limpia en JavaScript, el movimiento natural fue eliminar el paso de import por completo.

Yendo más lejos — del cleaner al generador completo

Una usuaria honesta marcó el gap: “Si todavía tengo que consolidar 4–7 filas del CSV por orden, esto es más complejo que un pivot table en Excel.” Tenía razón. El generador de reportes browser resuelve esto por completo: sube un CSV, recibe un Excel con P&L Statement y General Ledger. La consolidación, el netting de fees, el mapeo de asientos y la verificación de balance ocurren automáticamente. Lo que antes tomaba una hora ahora toma menos de un minuto.

Tres campos quedan deliberadamente en blanco: Ad Cost (Etsy cobra diario por click-through, no por orden — atribuirlos sería inventar data), Shipping Cost Paid (las filas de etiqueta muestran label number, no Order #, así que el match es poco confiable), y COGS (nunca está en el CSV; debe entrarse por Listing). Mejor dejar vacío con una razón honesta que llenar con un estimado que confunde.

The General Ledger output

The GL report generator outputs a General Ledger sheet inside the Excel file — one row per Dr/Cr line, sortable by Account, groupable by Period or JE Type, with running totals. Sum of Debits should equal Sum of Credits per JE — if they don’t, that’s your audit flag. The generator verifies this automatically and flags any imbalance.

One subtle decision: the GL aggregates by period, not by order. The first version produced one JE per order — a 100-order month gave 700+ GL lines, unmanageable. Standard practice for high-volume marketplaces is period-summary entries with the per-order detail in subsidiary records, so the GL now gets one JE 1, one JE 2, one JE 3, and one JE 4 per period (~11–15 lines per month regardless of volume). The per-order detail isn’t lost — it lives in the Transactions table in the same Excel file. This is exactly how professional accounting systems separate “general ledger” from “sub-ledgers.”

El output General Ledger

El generador de reportes produce una hoja General Ledger dentro del archivo Excel — una fila por línea de Dr/Cr, ordenable por Account, agrupable por Period o JE Type, con running totals. La suma de Debits debería igualar la suma de Credits por JE — si no, ahí está tu audit flag. El generador lo verifica automáticamente y marca cualquier desbalance.

Una decisión sutil: el GL se agrega por período, no por orden. La primera versión producía un JE por orden — un mes de 100 órdenes daba 700+ líneas GL, inmanejable. La práctica estándar para marketplaces de alto volumen es asientos resumen por período con el detalle per-order en registros subsidiarios, así que el GL ahora recibe un JE 1, un JE 2, un JE 3 y un JE 4 por período (~11–15 líneas por mes sin importar el volumen). El detalle per-order no se pierde — vive en la tabla Transactions dentro del mismo archivo Excel. Así separan los sistemas contables profesionales el “general ledger” de los “sub-ledgers.”

Trade-offs and what I deliberately left out

No COGS automation. Sellers still enter material cost manually per listing. Forcing every seller to enter perfect COGS would have killed adoption; the toolkit works without it, just with fewer KPIs.

No off-Etsy expenses. Early on I had an Operating Expenses table for things like design tools, packaging, photography. Those clutter the question the toolkit answers: “what is Etsy charging me?” — not “what’s my full P&L?” Sellers can use any other tool for the full P&L. I cut Operating Expenses entirely to keep the focus surgical.

No real-time API integration. Etsy’s API requires developer registration; most sellers won’t do that. CSV import is friction-free and works for everyone. An automated path via an automation platform is documented for sellers who want it.

Trade-offs y lo que dejé deliberadamente fuera

Sin automatización de COGS. Los sellers ingresan costo de material manualmente por listing. Forzar a cada seller a ingresar COGS perfecto habría matado la adopción; el toolkit funciona sin eso, solo con menos KPIs.

Sin gastos fuera de Etsy. Al principio tenía una tabla Operating Expenses para cosas como herramientas de diseño, empaque, fotografía. Eso ensucia la pregunta que el toolkit responde: “¿qué me cobra Etsy?” — no “¿cuál es mi P&L completo?” Los sellers pueden usar otra herramienta para el P&L completo. Corté Operating Expenses entera para mantener el foco quirúrgico.

Sin integración API en tiempo real. La API de Etsy requiere registro de developer; la mayoría de sellers no van a hacerlo. El import CSV es libre de fricción y funciona para todos. Hay un path automatizado vía una plataforma de automatización documentado para sellers que lo quieran.

What I learned

Three things that surprised me building this:

1. The Etsy fee schedule is a moving target. I initially built against 2024 fees, then had to re-verify every fee for May 2026. Any toolkit referencing third-party fees needs a clear “Last Verified” field — mine has one now in the About / Credits table.

2. Sellers don’t want more features — they want fewer. Earlier versions had Operating Expenses, Unit Costing, packaging tracking, design-tool subscription tracking. A user told me to cut all of it: “The question is what Etsy is charging me — don’t make me track unrelated subscriptions.” She was right.

3. The accounting layer is the differentiator. Plenty of Etsy seller spreadsheets exist online. None I found generate proper journal entries with Dr/Cr cascades. That’s the moat — not the data table, but the accounting opinion baked into the formulas.

Lo que aprendí

Tres cosas que me sorprendieron construyendo esto:

1. La estructura de fees de Etsy es un blanco móvil. Inicialmente construí con fees 2024 y después tuve que re-verificar cada fee para Mayo 2026. Cualquier toolkit que referencia fees de terceros necesita un campo “Last Verified” — el mío lo tiene ahora en la tabla About / Credits.

2. Los sellers no quieren más features — quieren menos. Versiones anteriores tenían Operating Expenses, Unit Costing, tracking de empaque, suscripción a herramientas de diseño. Una usuaria me dijo que cortara todo: “La pregunta es qué me cobra Etsy — no me hagas trackear suscripciones no relacionadas.” Tenía razón.

3. La capa contable es el diferenciador. Existen muchos spreadsheets de Etsy online. Ninguno que encontré genera asientos contables apropiados con cascadas de Dr/Cr. Ese es el moat — no la tabla de datos, sino la opinión contable embebida en las fórmulas.

Want to see it in action?

Open access, the live framework is one click away, and the design rationale is right here. If you’re an Etsy seller, copy the base and try it. If you’re a hiring manager, this is the kind of work I do — clean accounting opinions, transparent design choices, and bilingual delivery.

¿Quieres verlo en acción?

Acceso abierto, el framework en vivo está a un click, y el rationale de diseño está aquí. Si eres seller de Etsy, copia la base y pruébala. Si eres hiring manager, este es el tipo de trabajo que hago — opiniones contables limpias, decisiones de diseño transparentes, y entrega bilingüe.