E-Ticaret Panel
Mağazalar
Mağaza Düzenle
Mağaza Adı
XML Linki
Shopify Store Name
.myshopify.com
Access Token
API Version
2025-07 (En Güncel - Önerilen)
2025-04
2025-01
2024-10
2024-07
2024-04 (Legacy)
2024-01 (Legacy)
Mevcut: 2025-07
Kontrol Süresi
Saniye
Dakika
Saat
Gün
Product Path (Opsiyonel)
XML'de ürünlerin bulunduğu path
🏷️ Vendor (Marka) Filtreleme
📦 Tüm markalar işleniyor
← Ana sayfadan "Filtre Ekle" butonuyla vendor seçimi yapabilirsiniz
Converter Kodunuz
module.exports = function convert (item, utils = {}) { /* ── XML sarmallarını aç ───────────────── */ if (!item) return []; if (item.Root?.Urunler?.Urun) { const list = Array.isArray(item.Root.Urunler.Urun) ? item.Root.Urunler.Urun : [item.Root.Urunler.Urun]; return list.flatMap(u => convert(u, utils)); } if (item.Urunler?.Urun) { const list = Array.isArray(item.Urunler.Urun) ? item.Urunler.Urun : [item.Urunler.Urun]; return list.flatMap(u => convert(u, utils)); } if (item.Urun) item = item.Urun; // en içteyiz /* ── yardımcılar ───────────────────────── */ const get = v => { if (v == null) return ''; if (Array.isArray(v)) return get(v[0]); if (typeof v === 'object') { if ('_' in v) return String(v._).trim(); if ('Deger' in v) return String(v.Deger).trim(); if ('Tanim' in v) return String(v.Tanim).trim(); return ''; } return String(v).trim(); }; const toNum = v => { const n = parseFloat(String(v ?? '').replace(',', '.').trim()); return Number.isFinite(n) ? n : 0; }; const toPrice = v => { const n = toNum(v); return n >= 0 ? n.toFixed(2) : '0.00'; }; const uniqUrls = arr => { const set = new Set(), out = []; (arr || []).forEach(u => { const url = String(u || '').trim(); if (/^https?:\/\//i.test(url) && !set.has(url)) { set.add(url); out.push(url); } }); return out; }; const stripHtml = s => String(s || '').replace(/<[^>]*>/g,' ').replace(/\s+/g,' ').trim(); const norm = s => String(s || '').trim().replace(/\s+/g,' '); const safeColor = s => norm(s) || 'Renk Yok'; /* ── sabitler ──────────────────────────── */ const OPT1 = 'Beden'; const OPT2 = 'Renk'; const OPT3 = ''; /* ── temel alanlar ─────────────────────── */ const id = get(item.UrunKartiID) || ''; const rawTitle = get(item.UrunAdi) || 'İsimsiz Ürün'; const title = utils.normalizeTitle ? utils.normalizeTitle(rawTitle) : rawTitle; const vendorRaw = get(item.Marka) || 'Fame'; const vendor = utils.normalizeVendor ? utils.normalizeVendor(vendorRaw) : vendorRaw; const type = get(item.Kategori) || ''; const tags = get(item.KategoriTree) || ''; const onYazi = get(item.OnYazi); const aciklama = get(item.Aciklama); /* ── Set içeriği için özel alanlar ─────── */ const ozelSizeSpec = get(item.OzelAlan4); // ör. "S-M-L" veya "STANDART" const ozelQtySpec = get(item.OzelAlan5); // ör. "2-2-2" veya "5" /* ── teknik detaylar ───────────────────── */ let teknikList = []; (() => { let td = item.TeknikDetaylar; if (Array.isArray(td)) td = td[0]; if (td?.TeknikDetay) { const lst = Array.isArray(td.TeknikDetay) ? td.TeknikDetay : [td.TeknikDetay]; teknikList = lst .map(t => ({ name: get(t.OzellikTanim), val: get(t.DegerTanim) })) .filter(o => o.name || o.val); } })(); /* ── ürün görselleri ───────────────────── */ let imageUrls = []; (() => { let r = item.Resimler; if (Array.isArray(r)) r = r[0]; const raws = r?.Resim ? (Array.isArray(r.Resim) ? r.Resim : [r.Resim]) : []; imageUrls = uniqUrls(raws.map(get)); })(); /* ── varyant sarmalı ───────────────────── */ let secenekler = []; (() => { const wrap = item.UrunSecenek; if (!wrap) return; const wraps = Array.isArray(wrap) ? wrap : [wrap]; wraps.forEach(w => { const lst = w?.Secenek ? (Array.isArray(w.Secenek) ? w.Secenek : [w.Secenek]) : []; lst.forEach(s => s && secenekler.push(s)); }); })(); const pickOptionValue = (secenek, key) => { let ozl = []; let ek = secenek?.EkSecenekOzellik; if (Array.isArray(ek)) ek = ek[0]; if (ek?.Ozellik) ozl = Array.isArray(ek.Ozellik) ? ek.Ozellik : [ek.Ozellik]; for (const o of ozl) { let tanim = '', deger = ''; if (o.$) { tanim = o.$.Tanim || o.$.tanim || ''; deger = o.$.Deger || o.$.deger || ''; } if (!tanim) tanim = o.Tanim || o.tanim || o['@Tanim'] || ''; if (!deger) deger = o.Deger || o.deger || o['@Deger'] || ''; if (!deger) deger = o._ || o['#text'] || ''; if (String(tanim).trim().toLowerCase() === key.toLowerCase()) return String(deger).trim(); } return ''; }; /* ── ham varyant listesi ───────────────── */ const rawDetails = (secenekler.length ? secenekler : [{}]).map((s, idx) => { const sku = get(s.StokKodu) || `${id}-SKU${idx+1}`; const barcode = get(s.Barkod); const qty = parseInt(get(s.StokAdedi)||'0',10)||0; const indirim = toNum(get(s.IndirimliFiyat)); const rawPrice = indirim > 0 ? indirim : toNum(get(s.SatisFiyati)); const price = toPrice(rawPrice * 41); // Dolar → TL çevrim const paraBrm = 'TRY'; // Para birimini TL yap const renk = safeColor(pickOptionValue(s,'Renk')); const beden = norm(pickOptionValue(s,'Beden')) || 'STD'; const desi = toNum(get(s.Desi)); const grams = desi>0 ? Math.round(desi*1000) : 500; return { sku, barcode, qty, price, paraBrm, renk, beden, grams }; }); /* ── aynı beden‑renkleri birleştir ─────── */ const merged = new Map(); rawDetails.forEach(d => { const k = `${d.beden}||${d.renk}`; if (merged.has(k)) { const m = merged.get(k); m.qty += d.qty; if (!m.barcode && d.barcode) m.barcode = d.barcode; } else { merged.set(k, { ...d }); } }); let details = Array.from(merged.values()); // "let" – sonradan daraltacağız /* ── Standart setler için varyant filtresi ───── */ const isSTDSet = ozelSizeSpec && /standart/i.test(ozelSizeSpec); if (isSTDSet) { details = details.filter(d => d.beden.toUpperCase() === 'STD'); } /* ── Set İçerik Bilgisi (OzelAlan4 & OzelAlan5) ─ */ const buildSetContent = () => { if (!ozelSizeSpec) return ''; const splitBy = str => str.split(/[-,\/]/).map(s => s.trim()).filter(Boolean); const sizes = splitBy(ozelSizeSpec); const qtys = ozelQtySpec ? splitBy(ozelQtySpec) : []; const normalizeSize = s => { const up = s.toUpperCase(); if ([ 'STANDART','STD','STANDARD','ONE SIZE','ONE-SIZE','TEK', 'TEK BEDEN','TEKBEDEN' ].includes(up)) return 'STD'; return up; }; const pairs = sizes.map((sz, i) => { const size = normalizeSize(sz); const q = qtys[i] !== undefined ? qtys[i] : (qtys.length === 1 ? qtys[0] : ''); return q ? `${size}-${q}` : size; }); return pairs.join(' ').trim(); }; const setContent = buildSetContent(); /* ── açıklama HTML ─────────────────────── */ const buildDescriptionHTML = () => { const blocks = []; if (onYazi) blocks.push(onYazi); if (aciklama) blocks.push(aciklama); if (setContent) blocks.push('<strong>Set İçerik Bilgisi:</strong> '+setContent); if (teknikList.length) { const li = teknikList.map(t=>`<li><strong>${t.name}:</strong> ${t.val}</li>`).join(''); blocks.push('<h3>Teknik Detaylar</h3><ul>'+li+'</ul>'); } const rows = details.map(d=>` <tr> <td>${d.sku}</td><td>${d.renk}</td><td>${d.beden}</td> <td>${d.qty}</td><td>${d.price} ${d.paraBrm}</td> <td>${d.barcode||'-'}</td> </tr>`).join(''); blocks.push(` <h3>Varyasyonlar</h3> <table border="1" cellpadding="6" cellspacing="0"> <thead> <tr><th>SKU</th><th>Renk</th><th>Beden</th><th>Stok</th><th>Fiyat</th><th>Barkod</th></tr> </thead> <tbody>${rows}</tbody> </table>`.trim()); const barkodlar = [...new Set(details.map(d=>d.barcode).filter(Boolean))]; if (barkodlar.length) blocks.push('<strong>Barkod:</strong> '+barkodlar.join(' , ')); return blocks.join('<br/>'); }; // ── yardımcı: HTML içinden CSS'i temizler ───────────────────────────── function stripCss(html) { if (!html) return ''; let out = String(html); // <style> bloklarını KALDIR out = out.replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, ''); // HTML yorumlarını kaldır out = out.replace(/<!--[\s\S]*?-->/g, ''); // style=, class=, id= ve data-*, width/height gibi stil niteliği taşıyanları kaldır out = out.replace(/\s+(?:style|class|id|width|height)\s*=\s*"(?:[^"]*)"/gi, ''); out = out.replace(/\s+(?:style|class|id|width|height)\s*=\s*'(?:[^']*)'/gi, ''); out = out.replace(/\s+(data-[a-z0-9\-]+)\s*=\s*"(?:[^"]*)"/gi, ''); out = out.replace(/\s+(data-[a-z0-9\-]+)\s*=\s*'(?:[^']*)'/gi, ''); // Boş kalan çoklu boşlukları sadeleştir out = out.replace(/\s{2,}/g, ' ').trim(); return out; } const bodyHtml = buildDescriptionHTML(); const bodyHtmlClean = stripCss(bodyHtml); // ← CSS’siz const seoDesc = stripHtml(bodyHtmlClean).substring(0,160); /* ── handle ───────────────────────────── */ const base = `${id}-${title}`; const handle = utils.toHandle ? utils.toHandle(base) : base.toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-+|-+$/g,''); const PRODUCT_KEY = handle; /* ── şablon fonksiyonları ─────────────── */ const baseRow = () => ({ '__PRODUCT_KEY': PRODUCT_KEY, Handle: handle, Title:'', 'Body (HTML)': '', Vendor:'', Type:'', Tags:'', Published:'TRUE', 'Option1 Name':OPT1, 'Option1 Value':'', 'Option2 Name':OPT2, 'Option2 Value':'', 'Option3 Name':OPT3, 'Option3 Value':'', 'Variant SKU':'', 'Variant Grams':0, 'Variant Inventory Tracker':'shopify', 'Variant Inventory Qty':0, 'Variant Inventory Policy':'deny', 'Variant Fulfillment Service':'manual', 'Variant Price':'0.00', 'Variant Compare At Price':'', 'Variant Requires Shipping':'TRUE', 'Variant Taxable':'TRUE', 'Variant Barcode':'', 'Image Src':'', 'Image Position':'', 'Image Alt Text':'', 'Gift Card':'FALSE', 'SEO Title':'', 'SEO Description':'', 'Google Shopping / Google Product Category':'', 'Google Shopping / Gender':'female', 'Google Shopping / Age Group':'adult', 'Google Shopping / MPN':'', 'Google Shopping / Condition':'new', 'Variant Image':'', 'Variant Weight Unit':'kg', 'Variant Tax Code':'', 'Cost per item':'', Status:'active' }); const imageOnlyRow = (src,pos) => { const r = baseRow(); r.Published = ''; r['Variant Inventory Tracker'] = ''; r['Variant Inventory Qty'] = ''; r['Variant Inventory Policy'] = ''; r['Variant Fulfillment Service']=''; r['Variant Price'] = ''; r['Variant Requires Shipping'] = ''; r['Variant Taxable'] = ''; r['Variant Barcode'] = ''; r['Variant Grams'] = ''; r['Variant Weight Unit'] = ''; r.Status = ''; r['Image Src'] = src; r['Image Position'] = pos; r['Image Alt Text'] = title; return r; }; /* ── satırları derle ──────────────────── */ const rows = []; const emitted = new Set(); let imgPos = 1; const primary = imageUrls[0] || ''; details.forEach((d,idx)=>{ const r = baseRow(); if (idx===0) { r.Title = title; r['Body (HTML)'] = bodyHtmlClean; r.Vendor = vendor; r.Type = type; r.Tags = tags; r['SEO Title'] = title; r['SEO Description'] = seoDesc; } r['Option1 Value'] = d.beden; r['Option2 Value'] = d.renk; r['Variant SKU'] = d.sku; r['Variant Price'] = d.price; r['Variant Inventory Qty']= d.qty; r['Variant Barcode'] = d.barcode || ''; r['Variant Grams'] = d.grams; if (idx===0 && primary) { r['Image Src'] = primary; r['Image Position'] = imgPos++; r['Variant Image'] = primary; r['Image Alt Text'] = `${title} ${d.renk} ${d.beden}`; emitted.add(primary); } rows.push(r); }); /* ek görseller */ imageUrls.slice(1).forEach(src=>{ if (!emitted.has(src)) rows.push(imageOnlyRow(src,imgPos++)); }); return rows; };
Güncelle
İptal
İstatistikler
Toplam Çalışma
3474
Başarı Oranı
90%
İşlenen Ürün
0
Push Edilen
0