Shopify میں AJAX کارٹ دراز کیسے بنایا جائے (2026 طریقہ)

جب آپ اپنے Shopify اسٹور میں ڈیفالٹ طریقے سے کوئی پروڈکٹ شامل کرتے ہیں، تو پورا صفحہ دوبارہ لوڈ ہوجاتا ہے۔ ایک خریدار آپ کی مصنوعات کو دیکھتا ہے اور کلک کرتا ہے۔ ٹوکری میں شامل کریں۔براؤزر صفحہ کو رد کرتا ہے اور اسے دوبارہ بناتا ہے۔

سست روابط پر آپ کو 2-3 سیکنڈ کے لیے ایک خالی اسکرین نظر آئے گی۔ کبھی کبھی وہ اترتے بھی ہیں۔ /cartآپ جس چیز کو خریدنے کی کوشش کر رہے ہیں اس سے پورا صفحہ غائب ہو جاتا ہے، اور رفتار ختم ہو جاتی ہے۔

کارٹ دراز اس مسئلے کو حل کرتے ہیں۔ یہ سلائیڈ آؤٹ پینل ہے جو ظاہر ہوتا ہے جب کوئی آئٹم شامل کرتا ہے۔ خریداری کی ٹوکری کو اپ ڈیٹ کیا جاتا ہے، چیک آؤٹ بٹن وہیں ہے، اور خریدار کبھی بھی پچھلا صفحہ نہیں چھوڑتے ہیں۔

تقریباً ہر ہائی کنورٹنگ شاپائف اسٹور میں ایک ہوتا ہے، اور آپ کو اسے بنانے کے لیے کسی ایپ کی ضرورت نہیں ہے۔ اس کے لیے دو ایجیکس اینڈ پوائنٹس اور جاوا اسکرپٹ کی 100 سے کم لائنیں درکار ہیں۔

مسئلہ یہ ہے کہ زیادہ تر ٹیوٹوریلز اور زیادہ تر AI کوڈنگ ٹولز اسے کمزور طریقے سے بناتے ہیں۔ عمل درآمد کی گنتی کو جاوا اسکرپٹ متغیر میں رکھیں اور DOM کو براہ راست اپ ڈیٹ کریں۔ یہ ڈیمو میں اچھا لگتا ہے، لیکن جب پہلی دو لائنیں ایک میں ضم ہو جاتی ہیں، ایک رعایت لاگو ہوتی ہے، یا کلک اور چیک آؤٹ کے درمیان ویرینٹ فروخت ہو جاتا ہے تو یہ الگ ہو جاتا ہے۔

یہ گائیڈ ایک سینئر ڈویلپر کے نقطہ نظر سے بنایا گیا ہے، سرور ہمیشہ معلومات کا ذریعہ ہوتا ہے۔ پھر ہم ایک 2026 ایڈ آن دیکھیں گے جو درازوں کو وہی زبان بولنے کی اجازت دے گا جو ایپس اور AI شاپنگ ایجنٹوں کی ہے۔

ایک ساتھ کوڈ کرنے کے لیے، آپ ایک ڈویلپمنٹ تھیم کھول سکتے ہیں اور جاتے جاتے ہر حصے میں ترمیم اور تعمیر کر سکتے ہیں۔ یہاں ہر چیز پہلے سے طے شدہ آن لائن سٹور 2.0 تھیم (Horizon or Dawn) پر چلتی ہے جس میں کوئی ایپ انسٹال نہیں ہوتی۔

مکمل شدہ دراز: کارٹ میں شامل کریں، کوئی صفحہ دوبارہ لوڈ نہیں، اصل شاپنگ کارٹ کو ظاہر کرنے کے لیے پینل سلائیڈ کرتا ہے۔

انڈیکس

کیا تعمیر کرنا ہے

آخر میں، آپ کے پاس ایک دراز ہوگا جو اس طرح نظر آئے گا:

  • صفحہ کو دوبارہ لوڈ کیے بغیر ایجیکس کے ذریعے کارٹ میں شامل کریں۔

  • ہر بار جب کوئی تبدیلی کی جاتی ہے، ٹوکری کو دوبارہ پڑھا جاتا ہے اور اس کے جواب کو سچ سمجھا جاتا ہے۔

  • اپنا مواد اور سلائیڈیں کھولیں۔

  • ایک واحد مندوب سننے والے کے ساتھ مقدار پلس/مائنس ہینڈل کرتا ہے۔

  • لائن کو ہٹا دیں اور کارٹ کو خالی کریں۔

  • حتمی اپ گریڈ کے طور پر، یہ خود کو Shopify کے نئے معیاری اسٹور آپریشنز کے سامنے لاتا ہے تاکہ ایپس اور AI ایجنٹس انہیں چلا سکیں۔

شرطیں

  • ایک قابل تدوین Shopify تھیم (مثال کے طور پر ایک آن لائن سٹور 2.0 فرض کیا جاتا ہے، جیسے Horizon یا Dawn)

  • آرام fetch اور وعدہ

  • بنیادی مائع

  • کوئی ایپس، کوئی فریم ورک، کوئی تعمیراتی قدم نہیں۔

مرحلہ 1: دراز مارک اپ

دراز کو حصوں میں بنائیں تاکہ وہ تمام صفحات پر پیش کیے جائیں، پھر موجودہ کارٹ کو رینڈر کریں۔ مائع کا استعمال کرتے ہوئے سرور سائیڈ اس سے پہلے کہ جاوا اسکرپٹ کو عمل میں لایا جائے۔

یہ ضروری ہے۔ اگر کوئی خریدار اپنی ٹوکری میں اشیاء کے ساتھ پہلے سے ہی پہنچ جاتا ہے، تو دراز پہلے پینٹ پر درست ہے اور JavaScript کو تبدیلی کے بعد ہی اسے اپ ڈیٹ کرنے کی ضرورت ہے۔ یہ ایک بڑھتی ہوئی بہتری ہے اور اکثر گھریلو ساخت میں نظر انداز کرنے والی پہلی چیز ہوتی ہے۔

کہ data-* نیچے دی گئی خصوصیات مارک اپ اور اسکرپٹ کے درمیان معاہدے ہیں۔ جاوا اسکرپٹ کے ساتھ جو کچھ بھی ہوتا ہے اسے ان خصوصیات میں سے کسی ایک کے ذریعے دیکھا جاتا ہے، نہ کہ کلاس کے نام یا ٹیگ کے مقام کے ذریعے۔

{%- comment -%} sections/cart-drawer.liquid {%- endcomment -%}




دو تفصیلات یہاں توقف کے قابل ہیں: item.final_line_priceنہیں item.line_price. اگرچہ دونوں کارٹ میں موجود ہیں۔ final_line_price یہ خریداروں سے وصول کی جانے والی اصل رقم ہے، کیونکہ یہ لائن لیول کی چھوٹ کو ظاہر کرتی ہے۔ اور ہر ایک

  • لے جانا data-line-key اور data-quantityآپ مقدار اور ہٹانے کے کنٹرول کے بارے میں بعد میں پڑھیں گے۔

    شامل کریں بٹن پروڈکٹ کارڈ یا پروڈکٹ کے صفحہ پر واقع ہوتا ہے اور مختلف قسم کی ID کو براہ راست مائع سے پاس کرتا ہے، اس لیے ہر بار درست قسم شامل کی جاتی ہے۔

    {%- comment -%} in the product card / PDP {%- endcomment -%}
    
    

    مرحلہ 2: دوبارہ لوڈ کیے بغیر کارٹ میں شامل کریں۔

    یہاں ایک جملے میں مکمل نمونہ ہے: ٹوکری کو تبدیل کریں، پھر اسے دوبارہ پڑھیں، اسے پیش کریں، اور اسے کھولیں۔ جو لکھا ہے، POST /cart/add.js ایک قسم شامل کرنے کے لیے GET /cart.js میں پوری ٹوکری کو دوبارہ پڑھتا ہوں اور پھر درازوں کو پینٹ کرتا ہوں جس کے ساتھ میں واپس آیا ہوں۔

    // assets/cart-drawer.js
    document.querySelectorAll("[data-add]").forEach(function (btn) {
      btn.addEventListener("click", function () {
        var id = Number(btn.getAttribute("data-variant-id"));
        fetch("/cart/add.js", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ id: id, quantity: 1 }),
        })
          .then(function (r) { return r.json(); })
          .then(function () { return refresh(); })  // re-read /cart.js
          .then(openDrawer);                         // then slide it in
      });
    });
    

    ٹوکری کو دوبارہ کیوں پڑھیں؟ /cart/add.js پہلے ہی کچھ واپس کر دیا؟ کیونکہ ردعمل add.js یہ اس لائن کی وضاحت کرتا ہے جو آپ نے ابھی شامل کی ہے، پوری کارٹ کی نہیں، اور پوری ٹوکری دراز میں ظاہر ہوتی ہے۔

    زیادہ اہم بات یہ ہے کہ Shopify آپ کے حتمی شاپنگ کارٹ کا تعین کرتا ہے۔ آپ نئی لائنوں کو موجودہ لائنوں میں ضم کر سکتے ہیں، خودکار رعایتیں لاگو کر سکتے ہیں، یا فروخت ہونے والی مختلف قسموں کو مسترد کر سکتے ہیں۔ اس بات کا یقین کرنے کا واحد طریقہ یہ ہے کہ آپ کے دراز حقیقت سے میل کھاتے ہیں۔ بس refresh() اس پوری فائل میں یہ ایک واحد فنکشن ہے جو ہمیں شاپنگ کارٹ UI کو چھونے کی اجازت دیتا ہے۔

    function refresh() {
      return fetch("/cart.js").then(function (r) { return r.json(); }).then(render);
    }
    

    یہاں دونوں اختتامی نکات (/cart/add.js اور /cart.js) Shopify Ajax API کا حصہ ہے اور کسی بھی اسٹور کے ذریعے بغیر کسی سیٹ اپ کے استعمال کیا جا سکتا ہے۔

    مرحلہ 3 لوپ: خریدار Add to Cart پر کلک کرتا ہے، اسکرپٹ /cart/add.js پر پوسٹ کرتا ہے، پھر /cart.js کو دوبارہ پڑھتا ہے، پھر رینڈر کرتا ہے اور دراز کو کھولتا ہے۔

    اسے تبدیل کریں، اسے دوبارہ پڑھیں، اور پھر رینڈر کریں۔ ایک ہی لوپ اضافے، مقدار میں تبدیلی، اور ہٹانے کے لیے چلتا ہے۔

    مرحلہ 3: سرور پر دراز کو سچ میں پیش کرنا

    render(cart) خلل /cart.js جواب دیں اور دراز کھینچیں۔ غور کریں کہ کیا نہیں کیا جا رہا ہے۔ یہ کاؤنٹر میں کل اضافہ یا اضافہ نہیں کرتا ہے۔ یہ پڑھتا ہے item_count اور total_price میں نے اسے باکس سے باہر لے لیا جو Shopify واپس آیا۔

    function money(cents) {
      return "$" + (cents / 100).toFixed(2);
    }
    
    function render(cart) {
      document.querySelector("[data-cart-count]").textContent = cart.item_count;
      document.querySelector("[data-cart-subtotal]").textContent = money(cart.total_price);
    
      var itemsEl = document.querySelector("[data-drawer-items]");
      var emptyEl = document.querySelector("[data-drawer-empty]");
      itemsEl.innerHTML = "";
      if (!cart.items.length) { emptyEl.style.display = "block"; return; }
      emptyEl.style.display = "none";
    
      cart.items.forEach(function (line) {
        var li = document.createElement("li");
        li.className = "drawer__item";
        li.setAttribute("data-line", "");
        li.setAttribute("data-line-key", line.key);
        li.setAttribute("data-quantity", line.quantity);
        li.innerHTML =
          '' + (line' +
          '' + line.title + "" +
          '' + money(line.final_line_price) + "";
        itemsEl.appendChild(li);
      });
    }
    

    ایک چیز جو لوگوں کو دیوانہ بناتی ہے وہ ہے پیسہ۔ Ajax API قیمت اس طرح لوٹاتا ہے: سینٹ. مہنگی لائن $18.99 یہ کچھ اس طرح لوٹاتا ہے: 1899. اگر آپ 100 سے تقسیم کرنا بھول جاتے ہیں، تو اسے بھیج دیا جائے گا۔ $1,899 کافی کہ money() مددگار اس تبدیلی کو ایک جگہ پر انجام دیتا ہے۔

    ایک پروڈکشن نوٹ: یہ وہی ہے جو کہتا ہے: final_line_priceیہ لائن لیول کی چھوٹ کی عکاسی کرتا ہے اور اس وجہ سے خریداروں سے وصول کی جانے والی اصل رقم ہے (line_price رعایت سے پہلے قیمت۔) ملٹی کرنسی اسٹورز پر ہینڈ رولڈ ایکسچینجز money() Shopify اپنی کرنسی کا فارمیٹ استعمال کرتا ہے، لہذا علامتیں اور اعشاریہ فعال مارکیٹ کی پیروی کرتے ہیں۔

    ایک کافی شاپ کا کارٹ دراز کھلا ہوا ہے جس میں تصویر، عنوان، قیمت، ذیلی ٹوٹل، اور چیک آؤٹ بٹن کے ساتھ ایک آئٹم دکھایا گیا ہے۔

    مکمل طور پر پیش کردہ دراز /cart.js جواب شمار، لائنیں، اور ذیلی ٹوٹل سبھی سرور سے نکالے گئے ہیں۔

    مرحلہ 4: ایونٹ ڈیلیگیشن کے ذریعے پلس اور مائنس مقدار

    تمام دراز خریداروں کو مقدار کو ایڈجسٹ کرنے کی اجازت دیتے ہیں۔ پلس اور مائنس بٹنوں کو چین کرنے کا واضح طریقہ یہ ہے کہ بٹنوں کے ذریعے لوپ کریں اور ہر بٹن کے ساتھ ایک کلک ہینڈلر منسلک کریں۔ ایسا کرنے سے کنٹرول پہلی تبدیلی کے بعد کام کرنا بند کر دے گا۔

    اس کی وجہ یہ ہے: جب بھی کارٹ تبدیل ہوتا ہے فہرست کو دوبارہ رینڈر کریں۔ یہ اس کی جگہ لے لیتا ہے۔

  • آپ نے عنصر کے ساتھ منسلک ہینڈلر کو پچھلے عنصر کے ساتھ استعمال کیا تھا۔ نئے بٹن میں کوئی سننے والا نہیں ہے۔

    یہاں اصلاحات ہیں: تقریب کا وفد. ایک سننے والے کو غیر تبدیل شدہ والدین کے ساتھ منسلک کریں ( ), and when a click bubbles up, check what was actually clicked. One handler, and it keeps working through every re-render because the element it’s attached to never moves.

    var itemsEl = document.querySelector("[data-drawer-items]");
    
    itemsEl.addEventListener("click", function (e) {
      var inc = e.target.closest("[data-qty-inc]");
      var dec = e.target.closest("[data-qty-dec]");
      if (!inc && !dec) return;
    
      var line = e.target.closest("[data-line]");
      var key = line.getAttribute("data-line-key");
      var qty = Number(line.getAttribute("data-quantity"));
      var nextQty = inc ? qty + 1 : qty - 1;
    
      fetch("/cart/change.js", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: key, quantity: nextQty }),
      })
        .then(function (r) { return r.json(); })
        .then(render);
    });
    

    اس ورژن کے لیے: render() ہر لائن کے اندر ایک سٹیپر کنٹرول برآمد کرتا ہے۔

    li.innerHTML =
      '' + (line' +
      '' + line.title + "" +
      '' +
        '' +
        '' + line.quantity + "" +
        '' +
      "" +
      '' + money(line.final_line_price) + "";
    

    ایک تفصیل جسے آسانی سے غلط سمجھا جا سکتا ہے: تبدیلی کی درخواست بھیجی جاتی ہے۔ id: keyلائن کلیدیہ متغیر ID نہیں ہے۔ اگر آپ کے کارٹ میں آئٹم کی مختلف خصوصیات (کندہ کاری، گفٹ نوٹ) ہیں، تو آپ دو الگ الگ لائنوں پر ایک ہی تغیرات رکھ سکتے ہیں۔ کلید منفرد طور پر ایک قطار کی شناخت کرنا ہے۔ /cart/change.js چاہتے ہیں

    کوانٹیٹی سٹیپر انٹرایکشن: مائنس اور پلس بٹن والے آئٹمز اور درمیان میں مقدار اور ذیلی ٹوٹل کو اپ ڈیٹ کریں۔

    ایک ڈیلیگیٹڈ سامعین اب اور کسی بھی رینڈرنگ کے بعد تمام لائنوں کے لیے سٹیپرز کو چلاتا ہے۔

    مرحلہ 5: لائن اور خالی ٹوکری صاف کریں۔

    ایک نیا ڈویلپر آپ کی تلاش میں آ سکتا ہے۔ /cart/remove.jsلیکن یہ موجود نہیں ہے۔ Shopify کے شاپنگ کارٹ API سے لائنیں ہٹا دیں۔ ہے اسی مقدار کو 0 میں تبدیل کریں۔ /cart/change.js یہ وہ راستہ ہے جسے میں نے ابھی سٹیپر کے لیے استعمال کیا تھا۔ پوری ٹوکری کو صاف کرنے کا اپنا اختتامی نقطہ ہوتا ہے۔ /cart/clear.jsجسم کی ضرورت نہیں ہے۔

    // Remove: one delegated listener, quantity 0 deletes the line.
    itemsEl.addEventListener("click", function (e) {
      var remove = e.target.closest("[data-remove]");
      if (!remove) return;
      var key = e.target.closest("[data-line]").getAttribute("data-line-key");
      fetch("/cart/change.js", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: key, quantity: 0 }),
      })
        .then(function (r) { return r.json(); })
        .then(render);
    });
    
    // Clear: empty the whole cart, no body.
    document.querySelector("[data-cart-clear]").addEventListener("click", function () {
      fetch("/cart/clear.js", { method: "POST" })
        .then(function (r) { return r.json(); })
        .then(render);
    });
    

    ہر چیز کی طرح سرور کے جواب میں دونوں کو دوبارہ پیش کیا جاتا ہے۔ یہ وہ نظم و ضبط ہے جو ہٹائی گئی اشیاء کو شمار میں باقی رہنے سے روکتا ہے۔

  • DOM اور امید سے باہر۔ سرور سے بات کریں اور پھر جو کچھ سرور کہتا ہے اسے کھینچیں۔

    مرحلہ 6: سیکشن رینڈرنگ API کا استعمال کرتے ہوئے دوبارہ رینڈر کریں (آپ کون سا ورژن فراہم کریں گے)

    اس وقت تک ہر چیز جاوا اسکرپٹ میں دراز کے ایچ ٹی ایم ایل کو دوبارہ لکھ رہی ہے۔ یہ کام کرتا ہے، لیکن دیکھیں کہ اس کی قیمت کتنی ہے۔ دراز مارک اپ اب دو جگہوں پر ہے: ایک بار مرحلہ 1 میں مائع میں اور ایک بار اندرونی ٹیمپلیٹ سٹرنگ میں۔ render(). اگر آپ ڈیزائن کو تبدیل کرتے ہیں، تو دونوں کو ہمیشہ کے لیے مطابقت پذیری میں تبدیل ہونا پڑے گا۔

    Shopify کا جواب یہ ہے: بنڈل سیکشن رینڈرنگ. اسی درخواست میں جو کارٹ کو تبدیل کرتی ہے، ہم کارٹ اینڈ پوائنٹ سے دوبارہ پیش کردہ سیکشن HTML کو واپس کرنے کو کہتے ہیں۔ مارک اپ صرف مائع میں موجود ہے، اور سرور صارف کو مکمل ایچ ٹی ایم ایل ڈیلیور اور گرا دیتا ہے۔

    شامل کرکے اسے منتخب کریں: sections خریداری کی ٹوکری کی درخواست کے پیرامیٹرز:

    fetch("/cart/add.js", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        id: variantId,
        quantity: 1,
        sections: "cart-drawer",              // section id(s), comma-separated
        sections_url: window.location.pathname // optional render context
      }),
    })
      .then(function (r) { return r.json(); })
      .then(function (cart) {
        // Shopify returns rendered HTML under `sections`, keyed by id.
        var html = cart.sections["cart-drawer"];
        if (html) {
          document.querySelector("[data-drawer]").innerHTML =
            new DOMParser().parseFromString(html, "text/html")
              .querySelector("[data-drawer]").innerHTML;
        }
        openDrawer();
      });
    

    ایجیکس کارٹ API حوالہ اور سیکشن رینڈرنگ API دستاویزات سے کیا جاننا قیمتی ہے؟

    • بنڈل سیکشن رینڈرنگ یہاں سے دستیاب ہے: /cart/add, /cart/change, /cart/clearاور /cart/update.

    • sections کوما سے الگ کردہ فہرست (یا صف) پانچ سیکشن IDs تک۔

    • sections_url آپ کو شروع کرنا چاہئے۔ /. اگر چھوڑ دیا جائے تو، اس حصے کو موجودہ صفحہ کے تناظر میں پیش کیا جائے گا ( Referer ہیڈر)۔

    • پیش کردہ HTML ہے۔ sections JSON جواب کی کلید بطور سیکشن ID درج کی گئی۔

    • سیکشنز جو رینڈر کرنے میں ناکام رہتے ہیں، بشمول غیر موجود سیکشنز، اس طرح واپس کیے جاتے ہیں: null HTTP 200 استعمال کریں۔ ہمیشہ null کی حفاظت کریں۔

    • سیکشن IDs ہیں: section.id مائع یا id="shopify-section-[id]" ریپنگ پیپر پر۔ فائل کے نام سے پیش کردہ حصوں کے لیے، جیسے {% section 'cart-drawer' %} کو theme.liquid) ID ہے۔ cart-drawer. JSON ٹیمپلیٹ کے اندر آپ کو ایک متحرک ID اس طرح ملتی ہے: template--123__cart-drawer، لہذا چابی کو ہارڈ کوڈنگ کرنے سے پہلے ریپر کو چیک کریں۔

    جنرک سیکشن رینڈرنگ API (a GET کے ساتھ ?sections= یا ?section_id= ہر صفحہ کے یو آر ایل میں شامل کیا جاتا ہے) نان شاپنگ کارٹ اپ ڈیٹس جیسے صفحہ بندی کی تلاش یا لامحدود سکرولنگ کے لیے ایک ہی خیال ہے۔ Shopify کی اپنی ہدایات یہ ہیں: شاپنگ کارٹ میں تبدیلی کے نتیجے میں ہونے والے کسی بھی آپریشن کے لیے، میں الگ کالوں پر بنڈل سیکشنز کو پیش کرنے کو ترجیح دیتا ہوں کیونکہ اس سے راؤنڈ ٹرپ کا وقت بچتا ہے۔

    یہ کھلونا پیٹرن نہیں ہے۔ Shopify کا اپنا Horizon تھیم بالکل اسی طرح کارٹس چلاتا ہے۔ کارٹ کا جزو ہے۔ sections ان کی فہرست میں /cart/change.js کال کریں اور دوبارہ پیش کریں۔ response.sectionsاسے ہارڈ کوڈنگ کرنے کے بجائے، ہم ڈیٹا انتساب سے ہر سیکشن کی ID پڑھتے ہیں۔ یہ اوپر دیے گئے انتباہات کا پروڈکشن ورژن ہے۔ یہ نہ سمجھیں کہ IDs سادہ ہیں۔ cart-drawer. اس کے بجائے، پیش کردہ ریپر سے پڑھیں۔

    2026 اپ گریڈ: معیاری اسٹور ایونٹس اور ایکشن

    مذکورہ بالا تمام چیزیں Shopify کو لازوال بناتی ہیں۔ اب نئے حصے کے لیے۔

    17 جون 2026 کو، Shopify نے اسپرنگ ’26 ایڈیشن کے حصے کے طور پر معیاری اسٹور ایونٹس اور کارروائیاں شروع کیں اور اب عام طور پر دستیاب ہے۔

    آئیڈیاز اب تھیمز ہیں۔ اخراج DOM ایونٹس کا ایک معیاری سیٹ، سبھی کا نام ایک نام کی جگہ میں رکھا گیا ہے۔ shopify:) اور بے نقاب کاموں کا ایک معیاری سیٹ Shopify.actions. آپ کی ایپ یا AI شاپنگ ایجنٹ اب ہر تھیم کی نجی جاوا اسکرپٹ کو ریورس انجینئرنگ کرنے کے بجائے ایک معاہدے کے ذریعے آپ کے تمام اسٹورز کے ساتھ بات چیت کر سکتا ہے۔

    یہ سمجھنے کے لیے کہ یہ کیوں ضروری ہے، اس بات پر غور کریں کہ کس طرح ایک upsell ایپ کو تھیمز کے لیے کارٹ میں اضافے کا پتہ لگانے کے لیے استعمال کیا گیا جو اس نے پہلے کبھی نہیں دیکھا تھا۔

    چار برے اختیارات تھے: بندر پیچ۔ fetch فون سونگھو /cart/addہر تھیم کے لیے مختلف ناموں کے ساتھ حسب ضرورت ایونٹس حاصل کریں، اور سروے کریں۔ /cart.js سلیکٹر کے ساتھ کارٹ کاؤنٹ نوڈس کے لیے DOM کا موازنہ یا سکریپ کرنے کے لیے ٹائمر کا استعمال کریں۔ یہ سب ٹوٹ جاتے ہیں جب کوئی تاجر انہیں دوبارہ کھالتا ہے یا تھیمز کو تبدیل کرتا ہے۔

    یہ وہی کوڈ بھی ہے جو AI معاونین اس وقت تیار کرتے ہیں جب آپ انہیں "کارٹ میں شامل کرنے کے بعد کچھ کرنے” کو کہتے ہیں۔ اس کی وجہ یہ ہے کہ کمزور پیٹرن تربیتی ڈیٹا پر حاوی ہیں۔

    مسئلہ کبھی بھی ڈویلپر کی لاپرواہی کا نہیں تھا۔ نشانہ بنانے کے لیے کوئی مستحکم انٹرفیس نہیں تھا۔

    بائیں طرف، ہم چار کمزور طریقے دکھاتے ہیں جو ایپ کارٹ کی تبدیلیوں کا پتہ لگانے کے لیے استعمال کرتی ہے: پیچ کو بازیافت کرنا، تھیم سے متعلق واقعات کو سننا، cart.js پولنگ، اور DOM سکریپنگ۔ دائیں طرف ایک معیاری معاہدہ ہے۔ Shopify:cart:lines-update کو سبسکرائب کریں اور Shopify.actions کو کال کریں۔

    چار کمزور موضوعاتی تدبیریں ان معاہدوں کے لیے ایک اتحاد میں سمٹ جاتی ہیں جو ریسکن سے بچ جاتے ہیں۔

    اہم طور پر، یہ پرت اوپر دراز جو میں نے ابھی بنایا ہے۔ یہ ایجیکس API کو تبدیل نہیں کرتا ہے۔ دستاویز ایک ہی مواد پر مشتمل تھیم سائیڈ ایونٹس کو بھی دکھاتی ہے۔ /cart/add.js اور /cart.js میں نے ایک کال کی اور Shopify نے ایک اسسٹنٹ کو بھیجا جس کا واحد کام کال کو تبدیل کرنا تھا۔ /cart.js ایونٹ کے پے لوڈ کی قسم کا جواب دیتا ہے۔ تو آپ کا کوئی بھی کام رائیگاں نہیں جاتا۔ آپ ایک کھلا بیان دینے کی کوشش کر رہے ہیں۔

    واقعہ: تھیم دنیا کو بتاتی ہے کہ کیا ہوا۔

    ہر واقعہ استعمال کرتا ہے: shopify: نام کی جگہیں ہیں: category:action سب سے مخصوص عناصر (پروڈکٹ کارڈز، شاپنگ کارٹس، کلیکشن کنٹینرز) سے نام دینے کے پیٹرن، پاسز اور بلبلے document. پے لوڈ CamelCase فیلڈ کے ساتھ اسٹور فرنٹ گراف کیو ایل API کی شکل اختیار کرتا ہے۔

    واقعہ یہ مندرجہ ذیل صورتوں میں ہوتا ہے:
    shopify:page:view ہر بار جب صفحہ لوڈ ہوتا ہے۔
    shopify:product:view آپ کا پروڈکٹ نمایاں ہوگا۔
    shopify:product:select خریدار مختلف قسم کے انتخاب کو تبدیل کرتا ہے۔
    shopify:cart:view آپ شاپنگ کارٹ دیکھ سکتے ہیں۔
    shopify:cart:lines-update کارٹ لائنیں شامل، اپ ڈیٹ، یا ہٹا دی گئی ہیں۔
    shopify:cart:note-update شاپنگ کارٹ نوٹ تبدیل کریں۔
    shopify:cart:discount-update ڈسکاؤنٹ کوڈ لاگو یا حذف کر دیا گیا۔
    shopify:cart:error کارٹ کی تبدیلی ناکام ہو جاتی ہے۔
    shopify:collection:view مجموعہ کا صفحہ لوڈ کریں۔
    shopify:collection:update جمع کرنے کے فلٹرز یا چھانٹی کو تبدیل کریں۔
    shopify:search:update تلاش کا فلٹر یا ترتیب تبدیل کریں۔

    ایپس باقاعدہ DOM API کا استعمال کرکے سبسکرائب کرتی ہیں۔ کوئی SDK نہیں:

    document.addEventListener('shopify:cart:lines-update', (event) => {
      console.log(event.action, event.lines);
      event.promise?.then(({ cart }) => {
        console.log(cart.cost.totalAmount.amount);
      });
    });
    

    شاپنگ کارٹ، میمو، ڈسکاؤنٹ، پروڈکٹ کا انتخاب، کلیکشن اپ ڈیٹ، اور سرچ اپ ڈیٹ ایونٹس شامل ہیں۔ promise غیر مطابقت پذیر نتیجہ کی فیلڈ۔ اس کے بعد سننے والا فوری طور پر لوڈنگ یا پرامید حیثیت ظاہر کر سکتا ہے اور پھر تصدیق شدہ مواد کو پڑھ سکتا ہے۔ { cart } ایک بار جب کام حل ہوجائے

    اپنے تھیم سے ایونٹس ایکسپورٹ کریں۔

    ایونٹ لائبریری کی میزبانی Shopify CDN پر کی گئی ہے۔ اسے امپورٹ میپ کے ذریعے لوڈ کریں (ماڈیولر تھیمز جیسے ہورائزن کے لیے) یا اسے عالمی سطح پر تفویض کریں (ڈان اسٹائل تھیمز کے لیے)۔

    ایک تھیم ایونٹ کی کلاس بنا کر اور کال کرکے ایونٹ کو فائر کرتا ہے۔ dispatchEvent(). اگر آپ اسے غور سے پڑھیں تو آپ دیکھیں گے کہ مواد ایک جیسا ہے۔ /cart/add.js اور /cart.js مرحلہ 2 میں کالیں:

    import { CartLinesUpdateEvent, CartErrorEvent } from '@theme/standard-events';
    
    const deferred = CartLinesUpdateEvent.createPromise();
    element.dispatchEvent(new CartLinesUpdateEvent({
      action: 'add',
      context: 'product',
      lines: [{ merchandiseId: variantId, quantity: 1 }],
      promise: deferred.promise,
    }));
    
    try {
      const response = await fetch(window.Shopify.routes.root + 'cart/add.js', { method: 'POST', body, headers });
      if (!response.ok) throw new Error('Add to cart failed');
      const ajaxCart = await fetch(window.Shopify.routes.root + 'cart.js').then(r => r.json());
      deferred.resolve({
        cart: CartLinesUpdateEvent.createCartFromAjaxResponse(ajaxCart),
      });
    } catch (e) {
      element.dispatchEvent(new CartErrorEvent({ error: e.message, code: 'SERVICE_UNAVAILABLE' }));
      deferred.reject(e);
    }
    

    وہ خاموشی createCartFromAjaxResponse(ajaxCart) یہ کلاسک ایجیکس دراز اور نئے ایونٹ کے معاہدوں کے درمیان ایک پل ہے۔ یہ تمہارا ہے /cart.js ایونٹ ایک پے لوڈ کے ساتھ سٹور فرنٹ API کی شکل میں جواب دیتا ہے جس کی اسے توقع ہوتی ہے، لہذا آپ کے پاس پہلے سے موجود کوئی بھی دراز براہ راست منسلک ہو جائے گا۔

    عمل: دنیا رعایا سے کچھ کرنے کو کہتی ہے۔

    ٹاسکس غیر مطابقت پذیر افعال ہیں۔ Shopify.actionsاس کے اپنے اسکرپٹ ٹیگ کے بغیر تمام مائع اسٹورز میں انجکشن لگایا گیا۔

    // Add, update, or remove lines. Also handles note + discountCodes.
    const { cart, userErrors, warnings } = await Shopify.actions.updateCart({
      lines: [
        { merchandiseId: "gid://shopify/ProductVariant/123", quantity: 1 }, // add
        { id: "gid://shopify/CartLine/456", quantity: 5 },                  // update
        { id: "gid://shopify/CartLine/789", quantity: 0 },                  // remove
      ],
    });
    // Returns: Promise<{ cart, userErrors?, warnings? }>
    
    await Shopify.actions.openCart();                 // Promise
    const { cart } = await Shopify.actions.getCart(); // reads current cart
    

    ڈیفالٹس اسٹاک تھیم کے ساتھ بغیر کسی تبدیلی کے کام کریں گے۔ updateCart اسٹور فرنٹ API کو لکھتا ہے، جگہ پر تازہ ہوجاتا ہے، اور پورے صفحہ کو دوبارہ لوڈ کرنے پر واپس آتا ہے۔ openCart کھولیں۔ یا اگر عنصر موجود ہے، تو اسے ری ڈائریکٹ کرے گا: /cart. getCart موجودہ کارٹ پڑھیں۔ اور اگر تشکیل شدہ کام کامیاب ہو جاتا ہے تو رن ٹائم خود کار طریقے سے رہائی ایپ کالنگ میچنگ ایونٹ updateCart بھیجنے کی بالکل ضرورت نہیں ہے۔ shopify:cart:lines-update.

    درازوں کو چلانے کے لیے آپریشن کو اوور رائڈ کریں۔

    یہ انعام ہے۔ تھیمز اعمال کے لیے پہلے سے طے شدہ اقدار کو اوور رائیڈ کر سکتے ہیں، اس لیے مداخلت ممکن ہے۔ openCart اور updateCart صفحہ کی تازہ کاری کو متحرک کرنے کے بجائے، آپ کی ایپ کی تمام کالز اس دراز کے ذریعے روٹ کی جاتی ہیں جو آپ نے پہلے سے بنایا ہوا ہے۔ ایپ کو مارک اپ جاننے کی ضرورت نہیں ہے۔ معیاری آپریشنز کو کال کرنا اور ان کو اوور رائیڈ کرنا UI کی فعالیت کا تعین کرتا ہے۔

    اپنے اوور رائیڈ کو اندر رجسٹر کریں: DOMContentLoaded سننے والا رکھا پر {{ content_for_header }} لے آؤٹ ایپ کوڈ سے پہلے چلتے ہیں۔

    document.addEventListener('DOMContentLoaded', () => {
      Shopify.actions.updateCart.configure({
        eventTarget: (meta) => {
          if (meta.type === 'shopify:cart:note-update') return document.querySelector('cart-note');
          if (meta.type === 'shopify:cart:discount-update') return document.querySelector('cart-discount');
          if (meta.type === 'shopify:cart:lines-update' && meta.action === 'add') {
            return document.querySelector('product-form');
          }
          return document.querySelector('cart-items');
        },
        async handler(defaultHandler, payload, options) {
          const result = await defaultHandler();
          customUpdateUI(result); // your render() + openDrawer() from earlier
          return result;
        },
      });
    });
    

    openCart ایک آسان اوور رائڈ ہے:

    Shopify.actions.openCart.configure({
      handler() { document.querySelector('cart-drawer')?.open(); },
    });
    

    آپ کا وقت بچانے کے لیے چند اصول:

    • eventTarget کے لئے ضروری ہے updateCart. اس بات کا تعین کرتا ہے کہ آٹو ایمیشن ایونٹ کو کس عنصر کو بھیجا گیا ہے۔

    • getCart جان بوجھ کر ~ نہیں قابل ترتیب۔ کال کرنا configure() ٹائپ اسکرپٹ کی خرابیاں اور رن ٹائم کی خرابیاں ہیں۔ TypeError.

    • isDefault() یہ آپ کو بتاتا ہے کہ آیا تھیم نے ابھی تک کارروائی کو اوور رائڈ کیا ہے۔

    • updateCart کے ساتھ حل کریں { cart, userErrors?, warnings?, detail? } اسے صرف تب ہی مسترد کیا جائے گا جب یہ بالکل نہیں چل سکتا (نیٹ ورک کی خرابی یا غلط پے لوڈ)۔ کوئی راستہ نہیں userErrors ترتیب کا مطلب یہ ہے کہ اتپریورتن کو مسترد کر دیا گیا ہے، جیسے INVALID, MAXIMUM_EXCEEDED)۔ کوئی راستہ نہیں warnings ترتیب میں احتیاط کی ضرورت ہے (MERCHANDISE_OUT_OF_STOCK, DISCOUNT_NOT_FOUND)۔ اعتماد کرنے سے پہلے دونوں کو چیک کریں۔ cart.

    آپ کی ایپ یا AI ایجنٹ ایک معیاری کارروائی کو کال کرتا ہے، تھیم اسے آپ کی موجودہ کارٹ دراز منطق کے ذریعے روٹ کرتی ہے، اور دراز دوبارہ لوڈ کی ضرورت کے بغیر اپنی جگہ پر کھل جاتا ہے۔

    ایپ معیاری کارروائیوں کو کال کرتی ہے اور مارک اپ کے بارے میں کچھ نہیں جانتی ہے۔ اوور رائڈ UI کا تعین کرتا ہے۔

    چیک کر رہا ہے۔

    چلائیں shopify theme dev CLI ایونٹ کے رن ٹائم کی ایک ڈیولپمنٹ بلڈ لوڈ کرتا ہے، جو پے لوڈ کی توثیق کرتا ہے اور اگر فیلڈز خراب یا غائب ہیں تو انتباہات لاگ ان کرتا ہے۔

    یہ چیک پیداوار کے دوران ہٹا دیے جاتے ہیں۔ اضافہ --standard-events-inspector دو ٹیبز کے ساتھ مقامی صفحہ میں فلوٹنگ ڈیبگ پینل کو جھنڈا لگاتا ہے اور داخل کرتا ہے۔ واقعہتمام خارج ہونے والے معیاری واقعات کو ان کے مکمل پے لوڈ کے ساتھ حقیقی وقت میں دکھاتا ہے۔ عملآپ کاموں کو براہ راست ڈیلیور کرسکتے ہیں اور نتائج کا معائنہ کرسکتے ہیں۔ پے لوڈز کو زنجیر بناتے وقت، کسی بھی ٹیوٹوریل پر انسپکٹر پر بھروسہ کریں، بشمول یہ۔

    یہ کیوں اہمیت رکھتا ہے۔

    اس تعمیر کے پیچھے دو خیالات یہ ہیں کہ یہ کسی بھی مخصوص کوڈ کو ختم کرے گا اور کام کرنے والے دراز اور ایک دراز کے درمیان فرق ہے جسے آپ برقرار رکھ سکتے ہیں۔

    تقریب کا وفد

    والدین کی طرف سے ایک سننے والا جسے کبھی تبدیل نہیں کیا جائے گا، پڑھیں e.target.closest(...)تمام چائلڈ عناصر پر کارروائی کرتا ہے (جو فی الحال صفحہ پر ہیں اور وہ جو ابھی تک پیش نہیں کیے گئے ہیں)۔ اگر آپ اس کے بجائے ایک ہینڈلر کو فی بٹن باندھتے ہیں، تو یہ اس وقت ختم ہوجائے گا جب فہرست دوبارہ پیش کی جائے گی۔ یہ آپ کے کارٹ دراز میں مستقل طور پر رہے گا۔

    وفد بھی ایک غیر حادثاتی نمونہ ہے جو AI ٹولز یقینی طور پر غلط ہو جاتے ہیں۔ اس کی وجہ یہ ہے کہ تربیت کے اعداد و شمار میں عنصر کے ساتھ مخصوص پابندیاں سب سے زیادہ پائی جاتی ہیں۔ کسی وفد تک پہنچنے کا طریقہ جاننا بالکل اسی قسم کا فیصلہ ہے جو نحو سے نہیں آتا۔

    سیکشن رینڈرنگ API

    دراز کے مارک اپ کو دو جگہوں پر رکھنے اور اسے مطابقت پذیر رکھنے کی کوشش کرنے کے بجائے، آپ سرور کو سیکشنز رینڈر کرنے اور HTML پاس کرنے دیتے ہیں۔ مارک اپ ایک فائل میں موجود ہے اور بیچنے والے تھیم ایڈیٹر میں سیکشنز میں ترمیم کرنے کی وجہ سے درست رہتا ہے۔

    ڈیل ایک ہی مارک اپ کو دو بار برقرار نہیں رکھ رہی ہے، بلکہ تھوڑا بڑا ردعمل اور تجزیہ کرنے والا قدم ہے۔

    اور اس کے نیچے ایک قاعدہ ہے۔ خیال یہ ہے کہ ہر تبدیلی کے بعد کارٹ (یا پیش کردہ حصے) کو دوبارہ پڑھیں اور اسے سرور کے جواب سے پینٹ کریں۔ مقامی کاؤنٹر چھوٹی چھوٹی ہے۔ اس مضمون میں باقی سب کچھ سرور کے اعتماد پر ایک تغیر ہے۔

    مکمل فائل

    آپ میں سے ان لوگوں کے لیے جنہوں نے ابھی یہاں سکرول کیا ہے، یہ سب سیکشن مارک اپ، جاوا اسکرپٹ اور سی ایس ایس کے بارے میں ہے۔ JavaScript سرور کے جواب کے تمام ری رینڈرنگ کو یکجا کرتا ہے: شامل کریں، مقدار، ہٹائیں، اور صاف کریں۔

    sections/cart-drawer.liquid:

    
    
    
    
    
    {% schema %}
    { "name": "Cart drawer" }
    {% endschema %}
    

    assets/cart-drawer.js:

    (function () {
      var countEl = document.querySelector("[data-cart-count]");
      var itemsEl = document.querySelector("[data-drawer-items]");
      var emptyEl = document.querySelector("[data-drawer-empty]");
      var subtotalEl = document.querySelector("[data-cart-subtotal]");
      var drawer = document.querySelector("[data-drawer]");
      var scrim = document.querySelector("[data-drawer-scrim]");
      var clearBtn = document.querySelector("[data-cart-clear]");
    
      // --- Add to cart: mutate, re-read, render, open ---
      document.querySelectorAll("[data-add]").forEach(function (btn) {
        btn.addEventListener("click", function () {
          var id = Number(btn.getAttribute("data-variant-id"));
          fetch("/cart/add.js", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ id: id, quantity: 1 }),
          })
            .then(function (r) { return r.json(); })
            .then(function () { return refresh(); })
            .then(openDrawer);
        });
      });
    
      // --- Quantity +/- : one delegated listener on the stable list ---
      itemsEl.addEventListener("click", function (e) {
        var inc = e.target.closest("[data-qty-inc]");
        var dec = e.target.closest("[data-qty-dec]");
        if (!inc && !dec) return;
        var line = e.target.closest("[data-line]");
        var key = line.getAttribute("data-line-key");
        var qty = Number(line.getAttribute("data-quantity"));
        var nextQty = inc ? qty + 1 : qty - 1;
        fetch("/cart/change.js", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ id: key, quantity: nextQty }),
        }).then(function (r) { return r.json(); }).then(render);
      });
    
      // --- Remove a line: quantity 0 (there is no /cart/remove.js) ---
      itemsEl.addEventListener("click", function (e) {
        var remove = e.target.closest("[data-remove]");
        if (!remove) return;
        var key = e.target.closest("[data-line]").getAttribute("data-line-key");
        fetch("/cart/change.js", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ id: key, quantity: 0 }),
        }).then(function (r) { return r.json(); }).then(render);
      });
    
      // --- Clear the whole cart ---
      clearBtn.addEventListener("click", function () {
        fetch("/cart/clear.js", { method: "POST" })
          .then(function (r) { return r.json(); })
          .then(render);
      });
    
      // --- The one function that paints the drawer from the cart ---
      function money(cents) { return "$" + (cents / 100).toFixed(2); }
    
      function render(cart) {
        countEl.textContent = cart.item_count;
        subtotalEl.textContent = money(cart.total_price);
        itemsEl.innerHTML = "";
        if (!cart.items.length) { emptyEl.style.display = "block"; return; }
        emptyEl.style.display = "none";
        cart.items.forEach(function (line) {
          var li = document.createElement("li");
          li.className = "drawer__item";
          li.setAttribute("data-line", "");
          li.setAttribute("data-line-key", line.key);
          li.setAttribute("data-quantity", line.quantity);
          li.innerHTML =
            '' + (line' +
            '' + line.title + "" +
            '' +
              '' +
              '' + line.quantity + "" +
              '' +
            "" +
            '' + money(line.final_line_price) + "" +
            '';
          itemsEl.appendChild(li);
        });
      }
    
      function refresh() {
        return fetch("/cart.js").then(function (r) { return r.json(); }).then(render);
      }
      function openDrawer() { drawer.classList.add("is-open"); scrim.classList.add("is-open"); }
      function closeDrawer() { drawer.classList.remove("is-open"); scrim.classList.remove("is-open"); }
    
      document.querySelector("[data-cart-toggle]").addEventListener("click", function () { refresh().then(openDrawer); });
      document.querySelector("[data-drawer-close]").addEventListener("click", closeDrawer);
      scrim.addEventListener("click", closeDrawer);
    
      refresh(); // paint on load
    })();
    

    assets/cart-drawer.css:

    .drawer {
      position: fixed;
      inset: 0 0 0 auto;
      width: min(420px, 100%);
      background: #fff;
      transform: translateX(100%);
      transition: transform 0.3s ease;
      display: flex;
      flex-direction: column;
    }
    .drawer.is-open { transform: translateX(0); }
    .drawer__scrim {
      position: fixed; inset: 0;
      background: rgba(30, 18, 6, 0.45);
      opacity: 0; pointer-events: none;
      transition: opacity 0.3s ease;
    }
    .drawer__scrim.is-open { opacity: 1; pointer-events: auto; }
    

    ختم

    ہمارے پاس اب ایک کارٹ دراز ہے جو دوبارہ لوڈ کیے بغیر شامل کرتا ہے، اپ ڈیٹ کرتا ہے، ہٹاتا ہے اور صاف کرتا ہے، UI کو کبھی بھی اصل کارٹ سے بھٹکنے نہیں دیتا، اور ایکشن اوور رائیڈز کے ساتھ، انسانی اور AI ایجنٹس سمیت پورے ایپ ایکو سسٹم کو صاف عام انٹرفیس فراہم کرتا ہے۔

    ایجیکس فاؤنڈیشن برسوں سے ایک جیسی ہے۔ 2026 کی پرت اس کے اوپر رکھی گئی ہے، لہذا آپ جو دراز آج بنائیں گے وہ دستیاب رہے گا چاہے کل کچھ بھی ہو۔

    اگر آپ اس عین مطابق دراز کو کچھ جاوا اسکرپٹ لکھ کر انٹرایکٹو بنانا چاہتے ہیں اور یہ دیکھنا چاہتے ہیں کہ یہ اصلی اسٹورز میں کیسے رد عمل ظاہر کرتا ہے، تو آپ اسے یہاں مفت میں کرسکتے ہیں: learnshopify.dev.

    learnshopify.dev لینڈنگ پیج، Shopify ڈویلپمنٹ سیکھنے کے لیے ایک انٹرایکٹو پلیٹ فارم

  • Scroll to Top