Cum am transformat un export „murdar” într-un catalog pregătit pentru Shopify (doar cu Google Sheets)

Alpar Torok

Partea 1 - adăugare culori, aventura noastră recentă cu Google Sheets

Am pornit de la un export denormalizat (două seturi de id, culori amestecate în titlu, imagini separate). L-am curățat și l-am transformat într-un catalog import-ready pentru Shopify și un feed pregătit corect (GMC-ready), folosind doar Google Sheets. Ce am făcut:

  • Extragere culoare din titlul produsului cu regula „cea mai lungă denumire câștigă" (ex: „inalbit verde deschis" > „verde deschis" > „verde").
  • Completare automată HEX din tabelul de culori.
  • Propagare Culoare + HEX în lista finală după SKU.
  • Legare imagini după Product ID.
  • Feed pregătit pentru un setup Shopify corect (GMC-ready).
  • Formule pe toată coloana cu ARRAYFORMULA (scalabil, fără copy-paste).

1) Extragere Culoare Din Titlul Produsului (cea mai lungă potrivire)

Presupuneri: Titlul produsului este în S2.
În foaia Colors: B:B = Numele culorii, C:C = HEX.

Culoare (preferă potrivirea cea mai lungă)Locale SUA (virgule):

=IFERROR(
  INDEX(
    FILTER(Colors!B$2:B,
      REGEXMATCH(
        LOWER(" "&$S2&" "),
        "(^|[^[:alnum:]]|_)" &
        REGEXREPLACE(LOWER(Colors!B$2:B),"([.^$|?*+(){}[\\]\\-])","\\$1") &
        "($|[^[:alnum:]]|_)"
      )
    ),
    MATCH(
      MAX(LEN(
        FILTER(Colors!B$2:B,
          REGEXMATCH(
            LOWER(" "&$S2&" "),
            "(^|[^[:alnum:]]|_)" &
            REGEXREPLACE(LOWER(Colors!B$2:B),"([.^$|?*+(){}[\\]\\-])","\\$1") &
            "($|[^[:alnum:]]|_)"
          )
        )
      )),
      LEN(
        FILTER(Colors!B$2:B,
          REGEXMATCH(
            LOWER(" "&$S2&" "),
            "(^|[^[:alnum:]]|_)" &
            REGEXREPLACE(LOWER(Colors!B$2:B),"([.^$|?*+(){}[\\]\\-])","\\$1") &
            "($|[^[:alnum:]]|_)"
          )
        )
      ),
      0
    )
  ),
"")

HEX pentru culoarea găsită (dacă formula de mai sus e în T2):

=IF(T2<>"", IFERROR(VLOOKUP(T2, Colors!B$2:C, 2, FALSE), ""), "")

2) Culoare & HEX În „Final" După SKU

Presupuneri: În foaia Export: W=SKU, Y=Color Name, Z=Color Hex.
În foaia Final: R=SKU (ex. R2).

Culoare (lowercase) — curățăm spațiile invizibile, facem lookup pe coloană virtuală:

=IF(R2="","", LOWER(IFERROR(VLOOKUP(TRIM(R2), {ARRAYFORMULA(TRIM(Export!W:W)), Export!Y:Y}, 2, FALSE), "")))

HEX:

=IF(R2="","", IFERROR(VLOOKUP(TRIM(R2), {ARRAYFORMULA(TRIM(Export!W:W)), Export!Z:Z}, 2, FALSE), ""))

SKU duplicat (toate culorile distincte pentru același SKU):

=IF(R2="","", LOWER(TEXTJOIN(", ", TRUE, UNIQUE(FILTER(Export!Y:Y, TRIM(Export!W:W)=TRIM(R2))))))

3) Imagini După Product ID

Presupuneri: Foaia Images: A=Product ID, C=Image URLs, D=Variation images.
Foaia Final: A=Product ID (ex. A2).

Image URLs:

=IF(A2="","", IFNA(XLOOKUP(A2, Images!A:A, Images!C:C, ""), ""))

Variation images:

=IF(A2="","", IFNA(XLOOKUP(A2, Images!A:A, Images!D:D, ""), ""))

Pe toată coloana (umple B & C dintr-un foc) — pune în Final!B2 și lasă celulele de sub el goale:

=ARRAYFORMULA(
  IF(LEN(A2:A)=0, ,
    { IFNA(XLOOKUP(A2:A, Images!A:A, Images!C:C, "")),
      IFNA(XLOOKUP(A2:A, Images!A:A, Images!D:D, "")) }
  )
)

4) Feed Pregătit Corect Pentru Shopify (GMC-Ready)

  • Culori standardizate (cea mai lungă potrivire) + HEX coerent.
  • SKU unic → legături sigure între atribute și variante.
  • Titluri/Descrieri fără duplicarea culorii dacă ai câmp Color separat.
  • Metafields mapate (ex: product.metafields.specs.color).
  • Imagini corect asociate pe Product/Variant.
  • Preț/Promo consecvent.
  • Normalizează spații & diacritice înainte de import.

Capcane Frecvente & Soluții

  • Spații invizibile (CHAR 160): folosește SUBSTITUTE(TRIM(x),CHAR(160),"").
  • Text vs număr pentru ID/SKU: normalizează cu TO_TEXT(...).
  • Locale SUA: formulele de mai sus folosesc virgule ca separatori.

Vrei un mini-audit rapid pe catalogul tău?

Programare (max 30 min): Mini-audit Dalbe

Partea 2-a - Cum am rezolvat provocarea mapping-ului categoriilor în Google Sheets

Atunci când lucrezi cu mii de produse și categorii, nu e suficient să le ai doar într-un tabel. Trebuie să te asiguri că toate denumirile sunt coerente, cu sau fără diacritice, și că fiecare produs ajunge în categoria corectă.

Noi am creat o funcție personalizată în Google Sheets care face exact asta:

  • citește lista ta de categorii și subcategorii dintr-un sheet de tip „Mapping";
  • verifică dacă textul introdus are sau nu diacritice (ambele variante sunt acceptate);
  • folosește doar primul termen atunci când o celulă conține mai multe categorii separate prin virgulă;
  • returnează exact denumirea corectă, cu diacritice, așa cum trebuie să apară pe site;
  • iar dacă nu găsește nicio potrivire, pune categoria la „Altele" și păstrează termenul original ca subcategorie.

1. Creează sheet-ul Mapping

Adaugă un sheet nou în Google Sheets, denumit Mapping, cu următoarea structură:

Key Parent_name Category_name
produs tip A Categorie principală 1
subcategorie 1 Categorie principală 1 Subcategorie 1
produs tip B Categorie principală 2 Categorie B
sezon X Categorie sezonieră Sezon X
articol decorativ Categorie decor

2. Adaugă codul în Apps Script

Mergi la Extensions → Apps Script și inserează următorul cod:

const MAP_SHEET = 'Mapping';

function norm_(s) {
  return (s || '')
    .toString()
    .trim()
    .toLowerCase()
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '');
}

function loadMap_() {
  const sh = SpreadsheetApp.getActive().getSheetByName(MAP_SHEET);
  const last = sh.getLastRow();
  const vals = sh.getRange(2, 1, last - 1, 3).getValues();
  const map = {};
  vals.forEach(([key, parent, cat]) => {
    const k = norm_(key);
    if (k) map[k] = [parent || '', cat || ''];
  });
  return map;
}

function mapFirstToken_(input, map) {
  const original = (input || '').toString().trim();
  const firstToken = original.split(',')[0].trim();
  const firstNorm = norm_(firstToken);

  if (map[firstNorm]) return map[firstNorm];
  if (map[norm_(original)]) return map[norm_(original)];
  return ['Altele', firstToken];
}

function MAP_CAT(input) {
  const map = loadMap_();
  if (Array.isArray(input)) {
    return input.map(r => mapFirstToken_(r[0], map));
  }
  return [mapFirstToken_(input, map)];
}

3. Folosește formula în sheet-ul tău

Dacă ai categoriile brute în coloana A, inserează formula în B2:

=MAP_CAT(A2:A)

Coloana B va afișa Parent_name, iar coloana C Category_name. De acum, orice inconsistență este rezolvată automat: diacritice, multiple valori sau lipsa de mapping.

Unde am ajuns cu toate acestea

Astfel, am eliminat complet riscul de erori și am transformat o muncă manuală într-un proces automatizat, ușor de întreținut și prietenos cu SEO.

E un exemplu clar de cum putem îmbina un pic de programare cu organizarea datelor pentru a economisi timp și a aduce ordine în haos.

 

Partea 3 - Cum să combini două coloane cu coduri de bare în Google Sheets

Ai două coloane cu coduri de bare și vrei să le unifici într-una singură, cu prioritate pentru prima coloană? Mai jos ai formulele gata de folosit.

Regula

  • Dacă celula din prima coloană are valoare, o folosim pe aceea.
  • Dacă este goală, folosim valoarea din a doua coloană.

Formulă pentru un singur rând

Introduce în coloana țintă (ex. C2):

=IF(A2<>"", A2, B2)

Varianta pentru întreaga coloană (ARRAYFORMULA)

Nu mai e nevoie să tragi formula în jos; se aplică automat tuturor rândurilor începând cu rândul 2:

=ARRAYFORMULA(IF(A2:A<>"", A2:A, B2:B))
Opțional: adaugă un antet generat automat

Dacă vrei ca formula să scrie și un antet în primul rând al rezultatului:

=ARRAYFORMULA(IF(ROW(A2:A)=2, "Cod de bare combinat", IF(A2:A<>"", A2:A, B2:B)))
Sfat rapid: pornește din rândul 2 dacă rândul 1 este antet. Poți schimba A/B cu coloanele tale reale.

 

Partea 4 - Curățarea produselor duplicate după import - am crezut că suntem la ultimele 100 m

Când eram convinși că importul a mers bine și totul arată corect, Shopify ne-a surprins: în loc de o listă curată de produse, ne-am trezit cu produse duplicate. La început părea o problemă din platformă, dar după ce am analizat mai atent, am descoperit că eroarea era de fapt a noastră. Unele SKU-uri fuseseră asociate greșit în fișierul de import, iar Shopify le-a tratat ca produse separate.

Provocarea era clară: cum ștergem sute de duplicate fără să pierdem ore întregi făcând-o manual, produs cu produs? Am testat mai multe variante — corectarea CSV-ului, scripturi API și aplicații de tip bulk edit. În final, cea mai rapidă și sigură soluție a fost să folosim metoda tag-urilor. Am aplicat un tag tuturor produselor duplicate, le-am filtrat direct în Shopify și le-am șters în doar câteva click-uri, dar ca să ajungem la o taguire corectă, au trecut 8 ore. O greșeală atât de mică a avut un impact atât de mare.

Această etapă ne-a salvat ore bune de muncă manuală de a revizui fiecare produs (10000+ produse) și ne-a arătat din nou o lecție esențială: verifică întotdeauna fișierul de import înainte să rulezi pe un magazin live și păstrează mereu un backup, ca să fii pregătit dacă apar probleme.

Ce urmează?

Această aventură de 3 săptămâni cu Google Sheets ne-a arătat că nu există soluție perfectă din prima - dar cu răbdare și sistemul potrivit, poți transforma chiar și cele mai complexe provocări în procese automatizate.

Dacă te-ai confruntat cu provocări similare sau ai găsit soluții creative pentru gestionarea catalogului, ne-ar plăcea să auzim despre experiența ta în comentarii!

Pentru consultanță personalizată: Rezervă o sesiune de 30 min

P.S.: Cu ajutorul ChatGPT am reușit să facem ceva uimitor și într-un timp rezonabil pe acest proiect

Când am întrebat pe ChatGPT de o părere (for fun):
What you pulled off was basically taming chaos. You took an export that looked like a wild circus — colors tangled in titles, images wandering off on their own, duplicate IDs fighting for attention — and turned it into a neatly lined-up catalog, Shopify- and GMC-ready. In other words, you went from a squid splashing around in a bathtub to a well-trained dolphin show: same water, but now it makes sense.

If I had to sum it up bluntly, the last two days with the Client DB felt like wrestling a stubborn octopus in a small bathtub.

Every time we thought we had the structure under control, another hidden inconsistency, stray mapping, or messy field popped up. Instead of clean, predictable category data, we had duplicates, mixed formats, diacritics vs. no diacritics, and entries that looked like they were invented on the spot.

It’s the kind of thing that makes you question whether the original database was ever maintained with any kind of standard — or if every person who touched it in the last five years just “added their thing” without a second thought.

From a workflow perspective, this is one of those moments where the frustration isn’t just about the extra work, but about how much of this could have been avoided with some basic discipline and validation at the data entry stage. Now we’re burning hours untangling it instead of actually building the shop.

If I had to vent in one sentence (când am descoperit probelemele inițiale cu DB:

“We’ve spent 48 hours doing digital archaeology instead of e-commerce development.”

Înapoi la blog