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
// TOPSHOW XML (index.xml) -> Shopify CSV Converter // xml2js parse sonrası her element array içine sarılır module.exports = function productToShopifyRows(item, utils = {}) { // ---------- Helper Functions ---------- const trim = v => (v == null ? '' : String(v).trim()); const isUrl = u => /^https?:\/\//i.test(String(u || '')); const toNum = v => { if (v == null || v === '') return null; const n = Number(String(v).replace(',', '.')); return Number.isFinite(n) ? n : null; }; const money = v => { const n = toNum(v); return n == null ? '0.00' : n.toFixed(2); }; const uniq = arr => Array.from(new Set((arr || []).filter(Boolean))); const slugify = (s = '') => (utils.slugify ? utils.slugify(s) : String(s).toLowerCase().normalize('NFKD') .replace(/[\u0300-\u036f]/g, '') .replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '') ); const minifyHTML = (s = '') => String(s) .replace(/\s+/g, ' ') .replace(/\s*(>|\<)\s*/g, '$1') .trim(); // xml2js array unwrapper const val = v => { if (Array.isArray(v)) return val(v[0]); if (v && typeof v === 'object' && '_' in v) return val(v._); return v; }; const toArray = v => { if (v == null) return []; return Array.isArray(v) ? v : [v]; }; // Beden sırası const SIZE_ORDER = ['STD', 'S', 'M', 'L', 'XL', '2XL', '3XL']; const sizeRank = s => { const u = String(s || '').toUpperCase(); const i = SIZE_ORDER.indexOf(u); return i === -1 ? 999 : i; }; // ---------- LOT BAZLI Seri Parse ---------- const parseSeriBilgisi = (seriesText, totalQuantity) => { const text = trim(seriesText); if (!text) return { setInfo: '', variants: [] }; const variants = []; const parts = []; // Format 1: "S:2 / M:2 / L:2 = 6 Adet" if (text.includes(':') && text.includes('/')) { const matches = Array.from(text.matchAll(/([A-Z]+):(\d+)/g)); let lotSize = 0; const tempVariants = []; for (const match of matches) { const size = match[1]; const qtyPerLot = parseInt(match[2]); lotSize += qtyPerLot; tempVariants.push({ size, qtyPerLot }); parts.push(`${size}-${qtyPerLot}`); } // Lot sayısı = Quantity ÷ Lot Size const lotCount = lotSize > 0 ? Math.floor(totalQuantity / lotSize) : 0; tempVariants.forEach(v => { variants.push({ size: v.size, stock: v.qtyPerLot * lotCount }); }); } // Format 2: "TEK BEDEN 6 Adet" else if (/TEK\s+BEDEN/i.test(text)) { const qtyMatch = text.match(/(\d+)\s*Adet/i); const lotSize = qtyMatch ? parseInt(qtyMatch[1]) : 6; const lotCount = Math.floor(totalQuantity / lotSize); parts.push(`STD-${lotSize}`); variants.push({ size: 'STD', stock: lotSize * lotCount }); } const setInfo = parts.length > 0 ? `<p><strong>Set İçerik Bilgisi:</strong> ${parts.join(' ')}</p>` : ''; return { setInfo, variants }; }; // ---------- Name Parse ---------- const parseName = (name) => { const cleaned = trim(name); if (!cleaned) return { title: '', color: '' }; // Format: "Ürün Adı - Renk | Marka | KOD" const parts = cleaned.split('|').map(p => p.trim()); let title = parts[0] || ''; // Renk çıkar (son - sonrası) let color = ''; if (title.includes('-')) { const titleParts = title.split('-').map(p => p.trim()); color = titleParts[titleParts.length - 1]; title = titleParts.slice(0, -1).join(' - '); } return { title, color }; }; // ---------- Product Fields ---------- const productId = trim(val(item.Product_id)); const fullName = trim(val(item.Name)); const { title: productTitle, color: nameColor } = parseName(fullName); const description = trim(val(item.description)); const vendor = trim(val(item.Brand)) || 'TOPSHOW'; const productGroupId = trim(val(item.ProductGroupId)); const variantCode = trim(val(item.varyantkodu)); const singlePrice = toNum(val(item.Price)) || 0; const discountPrice = toNum(val(item['indirimli-Price'])) || 0; // Kategoriler - xml2js wraps in array const productTypeArr = toArray(item.ProductType); const categoryArr = toArray(productTypeArr[0]?.category || []); const categories = categoryArr.map(c => trim(val(c))).filter(Boolean); const tags = uniq([vendor, ...categories]).join(', '); // Handle const Handle = slugify([productTitle, productGroupId].filter(Boolean).join(' ')) || `product-${productId}`; // Resimler const images = []; for (let i = 1; i <= 5; i++) { const imgUrl = trim(val(item[`Image${i}`])); if (isUrl(imgUrl)) { images.push(imgUrl); } } // Fiyat (zaten TL olarak geliyor) const finalPrice = discountPrice > 0 ? discountPrice : singlePrice; const comparePrice = discountPrice > 0 ? singlePrice : 0; // ---------- Varyantlar ---------- const variantsArr = toArray(item.Variants); const variantArr = toArray(variantsArr[0]?.variant || []); if (variantArr.length === 0) { console.warn(`⚠️ No variants for product ${productId}`); } // ---------- CSV Rows ---------- const rows = []; variantArr.forEach((variant, vIndex) => { // Spec parse const specArr = toArray(variant.spec); let variantColor = nameColor; let seriesText = ''; specArr.forEach(spec => { const specName = val(spec.$?.name); const specValue = val(spec._ || spec); if (specName === 'Color') { variantColor = trim(specValue); } else if (specName === 'Series') { seriesText = trim(specValue); } }); const totalQuantity = parseInt(trim(val(variant.Quantity))) || 0; const barcode = trim(val(variant.barcode)); // Seri parse (LOT BAZLI) const { setInfo, variants: seriVariants } = parseSeriBilgisi(seriesText, totalQuantity); // Body HTML let bodyHTML = ''; if (setInfo) { bodyHTML = setInfo; } if (description) { bodyHTML += bodyHTML ? '\n' + description : description; } bodyHTML = minifyHTML(bodyHTML); // Base template - İLK SATIR const baseFull = { __PRODUCT_KEY: productId, Handle, Title: productTitle || `Product ${productId}`, 'Body (HTML)': bodyHTML, Vendor: vendor, Type: categories[0] || '', Tags: tags, Published: 'TRUE', 'Option1 Name': '', 'Option2 Name': '', 'Option3 Name': '', 'Variant Inventory Tracker': 'shopify', 'Variant Inventory Policy': 'deny', 'Variant Fulfillment Service': 'manual', 'Variant Requires Shipping': 'TRUE', 'Variant Taxable': 'TRUE', 'Gift Card': '', 'SEO Title': productTitle || '', 'SEO Description': description.substring(0, 160) || '', Status: 'active' }; // Base template - SONRAKI SATIRLAR const baseLite = { __PRODUCT_KEY: productId, Handle, Title: '', 'Body (HTML)': '', Vendor: '', Type: '', Tags: '', Published: '', 'Option1 Name': '', 'Option2 Name': '', 'Option3 Name': '', 'Variant Inventory Tracker': 'shopify', 'Variant Inventory Policy': 'deny', 'Variant Fulfillment Service': 'manual', 'Variant Requires Shipping': 'TRUE', 'Variant Taxable': 'TRUE', 'Gift Card': '', 'SEO Title': '', 'SEO Description': '', Status: '' }; if (seriVariants.length === 0) { // Seri yok - sadece renk varyantı const isFirst = vIndex === 0; const row = { ...(isFirst ? baseFull : baseLite) }; if (isFirst && variantColor) { row['Option1 Name'] = 'Renk'; } row['Option1 Value'] = variantColor || ''; row['Variant SKU'] = variantCode || productId; row['Variant Barcode'] = barcode; row['Variant Price'] = money(finalPrice); row['Variant Compare At Price'] = comparePrice > 0 ? money(comparePrice) : ''; row['Variant Inventory Qty'] = String(totalQuantity); if (isFirst && images.length > 0) { row['Image Src'] = images[0]; row['Image Position'] = '1'; row['Image Alt Text'] = productTitle; } rows.push(row); } else { // Seri var - Beden × Renk seriVariants.sort((a, b) => sizeRank(a.size) - sizeRank(b.size)); seriVariants.forEach((sizeVariant, sIndex) => { const isFirst = vIndex === 0 && sIndex === 0; const base = isFirst ? baseFull : baseLite; const row = { ...base, 'Option1 Name': isFirst ? 'Beden' : '', 'Option2 Name': isFirst && variantColor ? 'Renk' : '', 'Option1 Value': sizeVariant.size, 'Option2 Value': variantColor || '', 'Variant SKU': `${variantCode}-${sizeVariant.size}`, 'Variant Barcode': barcode, 'Variant Price': money(finalPrice), 'Variant Compare At Price': comparePrice > 0 ? money(comparePrice) : '', 'Variant Inventory Qty': String(sizeVariant.stock) }; if (isFirst && images.length > 0) { row['Image Src'] = images[0]; row['Image Position'] = '1'; row['Image Alt Text'] = productTitle; } rows.push(row); }); } }); // Ekstra resimler (sadece ilk varyant için) if (images.length > 1) { images.slice(1).forEach((imgUrl, i) => { rows.push({ __PRODUCT_KEY: productId, Handle, 'Image Src': imgUrl, 'Image Position': String(i + 2), 'Image Alt Text': productTitle }); }); } return rows; };
Güncelle
İptal
İstatistikler
Toplam Çalışma
4168
Başarı Oranı
79%
İşlenen Ürün
0
Push Edilen
0