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
// Shopify CSV converter – yalın "Beden Seti + Dağılım" metni, Sondaki Barkod // SKU artık hiçbir zaman opsiyon (variant option) olarak eklenmez. // Option1 = Beden, Option2 = Renk. SKU yalnızca Variant SKU alanında tutulur. module.exports = function convert(item, utils = {}) { if (!item) return []; // ---------- helpers ---------- const get = v => (Array.isArray(v) ? (v != null ? (v[0] ?? '') : '') : (v ?? '')); const txt = v => String(get(v) || '').trim(); const toPrice = val => { const s = String(val || '').replace(',', '.').trim(); const n = parseFloat(s); return isFinite(n) && n >= 0 ? n.toFixed(2) : '0.00'; }; const uniqUrls = list => { const arr = (list || []).filter(Boolean).map(String); const set = new Set(), out = []; for (const u of arr) { const url = u.trim(); if ((url.startsWith('http://') || url.startsWith('https://')) && !set.has(url)) { set.add(url); out.push(url); } } return out; }; const stripHtml = s => String(s || '').replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim(); // ---------- OPTION sabitleri ---------- const OPT1_NAME = 'Beden'; const OPT2_NAME = 'Renk'; // ---------- base ---------- const groupCode = txt(item.GroupProductCode) || txt(item.ProductCode) || 'grp'; const productCode = txt(item.ProductCode) || ''; const titleRaw = txt(item.ProductName_TR) || txt(item.ProductName_EN) || 'İsimsiz Ürün'; const title = utils.normalizeTitle ? utils.normalizeTitle(titleRaw) : titleRaw; const vendorRaw = txt(item.Brand) || 'XLove Jeans'; const vendor = utils.normalizeVendor ? utils.normalizeVendor(vendorRaw) : vendorRaw; const colorTR = txt(item.Color_TR) || ''; const colorEN = txt(item.Color_EN) || ''; const type = utils.normalizeProductType ? utils.normalizeProductType('Jean') : 'Jean'; const bodyBaseHtml = String(get(item.Model_Detail_TR) || '') .replace(/<br\s*\/?>/gi, '<br>') .trim(); const handleBase = `${groupCode}-${title}`; const handle = utils.toHandle ? utils.toHandle(handleBase) : handleBase.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''); const PRODUCT_KEY = handle; // ---------- collect variants ---------- let variants = []; (function collect() { const vc = item.Variants; if (!vc) return; const root = Array.isArray(vc) ? vc[0] : vc; if (!root) return; const list = root.Variant ? (Array.isArray(root.Variant) ? root.Variant : [root.Variant]) : []; variants = list.filter(Boolean); })(); // ---------- product-level images ---------- function getProductImageUrls() { const nodes = item.Images ? (Array.isArray(item.Images) ? item.Images : [item.Images]) : []; let urls = []; for (const cand of nodes) { if (cand && cand.Image) { const arr = Array.isArray(cand.Image) ? cand.Image : [cand.Image]; urls = urls.concat(arr.map(get)); } } return uniqUrls(urls); } function getVariantImageUrls(v) { if (!v || !v.Images) return []; const nodes = Array.isArray(v.Images) ? v.Images : [v.Images]; let urls = []; for (const cand of nodes) { if (cand && cand.Image) { const arr = Array.isArray(cand.Image) ? cand.Image : [cand.Image]; urls = urls.concat(arr.map(get)); } } return uniqUrls(urls); } const productImgsFallback = getProductImageUrls(); // ---------- grams ---------- function calcGrams(v) { const kg = parseFloat(String(get(v?.PackageWeightKG) || get(item.PackageWeightKG) || '0').replace(',', '.')) || 0; const pieces = parseInt(get(v?.ItemCountInAPackage) || get(item.ItemCountInAPackage) || '0', 10) || 0; const perPieceKg = pieces > 0 ? (kg / pieces) : kg; const grams = Math.round(perPieceKg * 1000); return grams > 0 ? grams : 500; } // ---------- price ---------- function pickPrice(v) { const fields = [ 'Price_Local_USD_Point','Price_Local_USD', 'Price_Global_USD_Point','Price_Global_USD', 'Price_Local_TL_Point','Price_Local_TL', 'Price_Global_TL_Point','Price_Global_TL' ]; for (const f of fields) { const p = toPrice(get(v && v[f])); if (p !== '0.00') { // Fiyatı 40.5 ile çarp const multiplied = parseFloat(p) * 40.5; return multiplied.toFixed(2); } } return '0.00'; } // ---------- build variant details ---------- function variantObjFromVariant(v, idx) { const sizeSet = txt(v.SizeSet) || 'Standart'; const sizeDistribution = txt(v.SizeDistribution); const skuRaw = txt(v.VariantStockCode) || `${groupCode}-${productCode}-IDX${idx + 1}`; const sku = utils.normalizeSKU ? utils.normalizeSKU(skuRaw) : skuRaw; const barcode = (utils.validateBarcode ? (utils.validateBarcode(txt(v.VariantBarcode)) || '') : txt(v.VariantBarcode)) || txt(item.Barcode) || ''; const priceUSD = pickPrice(v); const qty = parseInt(txt(v.RemainingStockPieces), 10) || 0; const itemCount = parseInt(txt(v.ItemCountInAPackage), 10) || 0; const lastUpdated = txt(v.LastUpdatedTime); const descTR = String(get(v.VariantDescription_TR) || '').replace(/<br\s*\/?>/gi, '<br>').trim(); const descEN = String(get(v.VariantDescription_EN) || '').replace(/<br\s*\/?>/gi, '<br>').trim(); const images = getVariantImageUrls(v); const html = descTR || descEN || (sizeDistribution ? `Beden Seti: ${sizeSet} - Dağılım: ${sizeDistribution}` : ''); return { sku, barcode, sizeSet, sizeDistribution, priceUSD, qty, itemCount, lastUpdated, descTR, descEN, html, images, colorTR, colorEN }; } let variantDetails = []; if (variants.length) { variantDetails = variants.map((v, idx) => variantObjFromVariant(v, idx)); } else { const sku = productCode || `${groupCode}-SKU`; const barcode = txt(item.Barcode) || ''; variantDetails = [{ sku, barcode, sizeSet: 'Standart', sizeDistribution: '', priceUSD: '0.00', qty: 0, itemCount: parseInt(txt(item.ItemCountInAPackage), 10) || 0, lastUpdated: '', descTR: '', descEN: '', html: '', images: productImgsFallback, colorTR, colorEN }]; } // ----------- YALIN "Beden & Dağılım" metni ----------- function buildSizeTextHTML(list) { const blocks = (list || []).map(o => { const set = o.sizeSet || 'Standart'; const dist = o.sizeDistribution || '-'; return `<p><strong>Beden Seti:</strong> ${set}<br><strong>Dağılım:</strong> ${dist}</p>`; }).join(''); return `<h3>Beden & Dağılım</h3>${blocks}`; } const sizeTextHTML = buildSizeTextHTML(variantDetails); const allBarcodes = Array.from(new Set(variantDetails.map(v => v.barcode).filter(Boolean))); const barcodeFooterHtml = allBarcodes.length ? `<br><strong>Barkod:</strong> ${allBarcodes.join(' , ')}` : ''; const variantDetailsJSON = JSON.stringify(variantDetails); // ---------- templates ---------- function baseRow() { return { '__PRODUCT_KEY': PRODUCT_KEY, 'Handle': '', 'Title': '', 'Body (HTML)': '', 'Vendor': '', 'Type': '', 'Tags': '', 'Published': 'TRUE', 'Option1 Name': '', 'Option1 Value': '', 'Option2 Name': '', 'Option2 Value': '', 'Option3 Name': '', 'Option3 Value': '', // boş bırakıldı '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', 'Variant Details (product.metafields.custom.variant_details_json)': '', 'Size Table (product.metafields.custom.size_table_html)': '' }; } function imageOnlyRow(handleValue, src, pos, alt, o1v, o2v) { return { '__PRODUCT_KEY': PRODUCT_KEY, 'Handle': handleValue, 'Title': '', 'Body (HTML)': '', 'Vendor': '', 'Type': '', 'Tags': '', 'Published': '', // Shopify isteği: Options DOLU olsun (Option3 artık YOK) 'Option1 Name': OPT1_NAME, 'Option1 Value': o1v || 'Standart', 'Option2 Name': OPT2_NAME, 'Option2 Value': o2v || (colorTR || 'Varsayılan'), 'Option3 Name': '', 'Option3 Value': '', 'Variant SKU': '', 'Variant Grams': '', 'Variant Inventory Tracker': '', 'Variant Inventory Qty': '', 'Variant Inventory Policy': '', 'Variant Fulfillment Service': '', 'Variant Price': '', 'Variant Compare At Price': '', 'Variant Requires Shipping': '', 'Variant Taxable': '', 'Variant Barcode': '', 'Image Src': src || '', 'Image Position': pos || '', 'Image Alt Text': alt || '', 'Gift Card': '', 'SEO Title': '', 'SEO Description': '', 'Google Shopping / Google Product Category': '', 'Google Shopping / Gender': '', 'Google Shopping / Age Group': '', 'Google Shopping / MPN': '', 'Google Shopping / Condition': '', 'Variant Image': '', 'Variant Weight Unit': '', 'Variant Tax Code': '', 'Cost per item': '', 'Status': '' }; } // ---------- images dedupe ---------- const emittedImages = new Set(); let nextImagePos = 1; function setVariantAndMaybeProductImage(row, url) { const u = String(url || '').trim(); if (!u) return; row['Variant Image'] = u; if (!emittedImages.has(u)) { row['Image Src'] = u; row['Image Position'] = String(nextImagePos++); emittedImages.add(u); } else { row['Image Src'] = ''; row['Image Position'] = ''; } } // ---------- tags ---------- function makeTags(extra = []) { const base = [colorTR, vendor, type, 'Mom Fit', groupCode && `Group:${groupCode}`].filter(Boolean).concat(extra); return utils.formatTags ? utils.formatTags(base) : base.join(', '); } const rows = []; // ---------- with variants ---------- if (variants.length) { const fv = variantDetails[0]; const firstSizeVal = utils.normalizeOption ? (utils.normalizeOption(fv.sizeSet) || 'Standart') : fv.sizeSet || 'Standart'; const firstColorVal = utils.normalizeOption ? (utils.normalizeOption(colorTR || 'Varsayılan') || 'Varsayılan') : (colorTR || 'Varsayılan'); variants.forEach((v, idx) => { const det = variantDetails[idx]; const sizeVal = utils.normalizeOption ? (utils.normalizeOption(det.sizeSet) || 'Standart') : (det.sizeSet || 'Standart'); const colorVal = firstColorVal; const sku = det.sku; const barcode = det.barcode; const price = det.priceUSD; const grams = calcGrams(v); const qty = det.qty; const vImgs = det.images && det.images.length ? det.images : productImgsFallback; const r = baseRow(); r['Handle'] = handle; r['Title'] = idx === 0 ? title : ''; r['Vendor'] = idx === 0 ? vendor : ''; r['Type'] = idx === 0 ? type : ''; r['Tags'] = idx === 0 ? makeTags([det.sizeSet]) : ''; r['Published'] = 'TRUE'; r['Option1 Name'] = OPT1_NAME; r['Option1 Value'] = sizeVal; r['Option2 Name'] = OPT2_NAME; r['Option2 Value'] = colorVal; // Option3 boş bırakılıyor r['Variant SKU'] = sku; r['Variant Price'] = price; r['Variant Inventory Qty'] = qty; r['Variant Barcode'] = barcode; r['Variant Grams'] = grams; if (idx === 0) { r['Body (HTML)'] = bodyBaseHtml + (sizeTextHTML ? '<br>' + sizeTextHTML : '') + barcodeFooterHtml; r['SEO Title'] = title; r['SEO Description'] = stripHtml(bodyBaseHtml).substring(0, 160); r['Variant Details (product.metafields.custom.variant_details_json)'] = variantDetailsJSON; r['Size Table (product.metafields.custom.size_table_html)'] = sizeTextHTML; } const primary = vImgs[0] || productImgsFallback[0] || ''; setVariantAndMaybeProductImage(r, primary); if (!r['Image Alt Text']) r['Image Alt Text'] = `${title} ${colorTR || colorEN}`.trim(); rows.push(r); // image-only satırlar (Option1 ve Option2 DOLU, Option3 boş) for (let i = 1; i < vImgs.length; i++) { const url = vImgs[i]; if (!url || emittedImages.has(url)) continue; rows.push( imageOnlyRow( handle, url, String(nextImagePos++), `${title} - ${colorVal} - ${sizeVal} - ${i + 1}`, firstSizeVal, firstColorVal ) ); emittedImages.add(url); } }); return rows; } // ---------- no variants ---------- const sizeVal = 'Standart'; const colorVal = utils.normalizeOption ? (utils.normalizeOption(colorTR || 'Varsayılan') || 'Varsayılan') : (colorTR || 'Varsayılan'); const sku = productCode || `${groupCode}-SKU`; const barcode = txt(item.Barcode) || ''; const price = '0.00'; const grams = calcGrams(null); const qty = 0; const vImgs = productImgsFallback; const r = baseRow(); r['Handle'] = handle; r['Title'] = title; r['Vendor'] = vendor; r['Type'] = type; r['Tags'] = makeTags(); r['Published'] = 'TRUE'; r['Option1 Name'] = OPT1_NAME; r['Option1 Value'] = sizeVal; r['Option2 Name'] = OPT2_NAME; r['Option2 Value'] = colorVal; r['Variant SKU'] = sku; r['Variant Price'] = price; r['Variant Inventory Qty'] = qty; r['Variant Barcode'] = barcode; r['Variant Grams'] = grams; const bodyHtml = bodyBaseHtml + (sizeTextHTML ? '<br>' + sizeTextHTML : '') + barcodeFooterHtml; r['Body (HTML)'] = bodyHtml; r['SEO Title'] = title; r['SEO Description'] = stripHtml(bodyBaseHtml).substring(0, 160); r['Variant Details (product.metafields.custom.variant_details_json)'] = variantDetailsJSON; r['Size Table (product.metafields.custom.size_table_html)'] = sizeTextHTML; const primary = vImgs[0] || ''; setVariantAndMaybeProductImage(r, primary); if (!r['Image Alt Text']) r['Image Alt Text'] = `${title} ${colorTR || colorEN}`.trim(); rows.push(r); for (let i = 1; i < vImgs.length; i++) { const url = vImgs[i]; if (!url || emittedImages.has(url)) continue; rows.push( imageOnlyRow( handle, url, String(nextImagePos++), `${title} - ${colorVal} - ${sizeVal} - ${i + 1}`, sizeVal, colorVal ) ); emittedImages.add(url); } return rows; };
Güncelle
İptal
İstatistikler
Toplam Çalışma
4484
Başarı Oranı
94%
İşlenen Ürün
0
Push Edilen
0