לוגיקת הנחות ומשלוחים מותאמת אישית עם Shopify Functions
תארו לעצמכם חנות בגדים מקוונת שרוצה להציע הנחה של 15% על הפריט השני בעגלה, אבל רק ללקוחות במוסקבה וכשהסכום הכולל הוא לפחות 60 דולר. הנחות סטנדרטיות של Shopify לא יכולות לבדוק מיקום גיאוגרפי או להתחשב בהרכב העגלה ברמת הפריט. הפתרון הוא Shopify Functions — הוקים סינכרוניים שפועלים במהלך חישוב העגלה מבלי לצאת מתשתית Shopify. תוך 5 אלפיות השנייה, אנחנו יכולים להחיל כללי הנחה או משלוח מורכבים מבלי להגדיל את זמן התשלום. לפי Shopify, עד 20% מהמשתמשים נוטשים את תהליך התשלום אם הוא אורך יותר משתי שניות, ולכן אופטימיזציה של Shopify Checkout עם פונקציות מותאמות אישית הופכת לסטנדרט עבור חנויות גדולות. הצוות שלנו מתקין פונקציות כאלה במפתח סגור: מהנחות פשוטות ועד משלוחים מבוססי מיקום גיאוגרפי מורכבים. עלות הפיתוח היא אישית, החיסכון בהשוואה למיקרוסרוויסים חיצוניים מגיע ל-30%, וערך העגלה הממוצע עולה ב-15–25% לאחר יישום הנחות מותאמות אישית.
למה Shopify Functions מהירים יותר מ-API חיצוניים
פונקציות פועלות בתוך תהליך התשלום — הן לא API חיצוניים שמבצעים בקשות HTTP. הן מתקמפלות ל-WebAssembly (Rust) או משתמשות ב-Javy runtime (JavaScript) ומבוצעות במגבלת 5–10 אלפיות השנייה. אין קריאות רשת, כל הנתונים מועברים דרך input.graphql. זה מבטיח ביצועים צפויים ואפס השהיה מורגשת למשתמש. עוד על הארכיטקטורה ב-תיעוד Shopify Functions.
איפה פונקציות עובדות
| Function API | מטרה |
|---|---|
cart_transform |
שינוי שורות העגלה לפני התשלום (חבילות, שינויים) |
discounts |
הנחות מותאמות אישית (קבועות, אחוזים, BXGY) |
payment_customization |
הסתרה/שינוי שם של אמצעי תשלום |
shipping_discount |
הנחה על משלוח |
delivery_customization |
הסתרה/שינוי שם/מיון של שיטות משלוח |
fulfillment_constraints |
אילוצים על פיצול משלוחים |
order_routing |
ניתוב הזמנות למחסנים |
פונקציות נכתבות ב-Rust (מתורגם ל-WebAssembly) או ב-JavaScript/TypeScript (דרך Javy runtime). Rust מועדף ללוגיקה מורכבת — מהיר יותר וחסכוני יותר במגבלות. פיתוח Shopify Functions כולל עיצוב input.graphql ו-Metafields.
איך ליישם הנחות מורכבות ללא פגיעה בביצועים
אנחנו משתמשים ב-Rust או TypeScript, ומבצעים אופטימיזציה לכל שאילתה. כל הכנת הנתונים מועברת לרמת Metafields — הפונקציה מקבלת קונפיגורציות מוכנות ומפעילה אותן תוך אלפיות השנייה. הניסיון שלנו מראה: עם עיצוב נכון, פונקציה נכנסת במגבלת 5 אלפיות השנייה אפילו עם 5 רמות קינון. בפרויקט אחד, יישמנו הנחה שמתחשבת בהיסטוריית הזמנות דרך Metafields: הפונקציה טענה JSON עם ספים ל-30 הימים האחרונים והחילה הנחה מוגדלת ללקוחות נאמנים — הכל במגבלת 4 אלפיות השנייה. הגדרת הנחות Shopify עם Functions מאפשרת ליישם כל כללי עסקים מבלי להאט את התשלום.
דוגמה: הנחת כמות (JavaScript)
input.graphql — מתאר אילו נתונים Shopify יעביר לפונקציה:
# input.graphql query RunInput {
cart {
lines {
id
quantity
merchandise {
... on ProductVariant {
id
product {
id
tags
metafield(namespace: "custom", key: "volume_discount_tier") {
value
}
}
}
}
}
}
discountNode {
metafield(namespace: "custom", key: "tiers") {
value
}
}
}# input.graphql query RunInput { cart { lines { id quantity merchandise { ... on ProductVariant { id product { id tags metafield(namespace: "custom", key: "volume_discount_tier") { value } } } } } } discountNode { metafield(namespace: "custom", key: "tiers") { value } } } — לוגיקת הפונקציה:
import type { RunInput, FunctionRunResult } from "../generated/api";
interface DiscountTier {
quantity: number;
percentage: number;
}
export function run(input: RunInput): FunctionRunResult {
const tiersJson = input.discountNode?.metafield?.value;
const tiers: DiscountTier[] = tiersJson ? JSON.parse(tiersJson) : [];
if (!tiers.length) {
return { discounts: [], discountApplicationStrategy: "FIRST" };
}
const discounts = [];
for (const line of input.cart.lines) {
const variant = line.merchandise;
if (variant.__typename !== "ProductVariant") continue;
const product = variant.product;
if (!product.tags.includes("volume-eligible")) continue;
const applicableTier = tiers
.filter(t => line.quantity >= t.quantity)
.sort((a, b) => b.quantity - a.quantity)[0];
if (!applicableTier) continue;
discounts.push({
targets: [{ cartLine: { id: line.id } }],
value: { percentage: { value: String(applicableTier.percentage) } },
message: `Скидка ${applicableTier.percentage}% за количество (от ${applicableTier.quantity} шт.)`,
});
}
return {
discounts,
discountApplicationStrategy: "FIRST",
};
} איך להגדיר משלוח מבוסס מיקום גיאוגרפי
אנחנו משתמשים ב-API של src/run.ts. הפונקציה מקבלת את כתובת המשלוח דרך input.graphql ויכולה להסתיר או לסדר מחדש שיטות משלוח. לדוגמה, עבור אזורים מרוחקים עם זמני משלוח ארוכים, אנחנו מסתירים שיטות אקספרס. הלוגיקה נכתבת ב-Rust למהירות מקסימלית — זמן ביצוע טיפוסי הוא 3 אלפיות השנייה. לשילוב, פנו למהנדסים שלנו. משלוח מותאם אישית עם מיקום גיאוגרפי הוא אחד השימושים הנפוצים של Functions.
אילוצי Shopify למשלוחים
| אילוץ | ערך | פתרון |
|---|---|---|
| זמן ביצוע | 5 אלפיות השנייה (Rust/WASM), 10 אלפיות השנייה (JS) | מזעור איטרציות, שמירת נתונים ב-Metafields |
| זיכרון | 10 MB | אל תטענו מערכי JSON גדולים — השתמשו ב-pagination ברמת השאילתה |
| בקשות רשת | אסורות | העבירו את כל הנתונים דרך input.graphql |
| גישה למסד נתונים | אין | אחסנו קונפיגורציות מורכבות ב-Metafields |
תהליך
- ניתוח — פירוק כללי עסקים, עיצוב נתוני קלט.
- עיצוב — בחירת שפה ואופטימיזציה של שאילתות למגבלות.
- יישום — כתיבת קוד, הכנת input.graphql ו-Metafields.
- בדיקות — מקומית דרך
import type { RunInput, FunctionRunResult } from "../generated/api"; interface DiscountTier { quantity: number; percentage: number; } export function run(input: RunInput): FunctionRunResult { const tiersJson = input.discountNode?.metafield?.value; const tiers: DiscountTier[] = tiersJson ? JSON.parse(tiersJson) : []; if (!tiers.length) return { discounts: [], discountApplicationStrategy: "FIRST" }; const discounts = []; for (const line of input.cart.lines) { const variant = line.merchandise; if (variant.__typename !== "ProductVariant") continue; const product = variant.product; if (!product.tags.includes("volume-eligible")) continue; const applicableTier = tiers .filter(t => line.quantity >= t.quantity) .sort((a, b) => b.quantity - a.quantity)[0]; if (!applicableTier) continue; discounts.push({ targets: [{ cartLine: { id: line.id } }], value: { percentage: { value: String(applicableTier.percentage) } }, message: `Скидка ${applicableTier.percentage}% за количество (от ${applicableTier.quantity} шт.)`, }); } return { discounts, discountApplicationStrategy: "FIRST", }; }אוdelivery_customization, ולאחר מכן על staging. - פריסה — דרך Shopify CLI, הפעלה ב-Admin.
לוחות זמנים תלויים במורכבות: הנחה פשוטה מיומיים עסקיים, פונקציה עם לוגיקת מיקום גיאוגרפי עד שבועיים.
בדיקות ופריסה
npm run test # или cargo test shopify app deploy shopify app logs # просмотр логов פקודות דיבאג נוספות
shopify app log --tail מה כוללת העבודה שלנו
- עיצוב ארכיטקטורת פונקציות תוך התחשבות במגבלות
- כתיבת קוד ב-Rust או TypeScript
- פיתוח סכמות input.graphql ו-Metafield
- פריסה ושילוב עם Admin
- תיעוד על הגדרת כללים
- תמיכה לאחר השקה (חודש)
הצוות שלנו מורכב ממפתחי Shopify מוסמכים עם ניסיון של 5+ שנים ו-30+ פרויקטים מיושמים. נבחן את המשימה שלכם תוך יום עסקים אחד. צרו קשר — נעזור ליישם לוגיקת הנחות ומשלוחים מותאמת אישית שלא מאטה את התשלום. קבלו ייעוץ.







