במהלך ניתוח משפך מכירות באתר מסחר אלקטרוני עם 50,000 ביקורים חודשיים, גילינו ש-40% מהתנועה הגיעה לעמוד הקטלוג אך לא המשיכה הלאה. דוחות סטנדרטיים הראו רק שיעור המרה של 2.5% בשלב זה אך לא הסבירו מדוע. דיאגרמת Sankey עזרה לחשוף שמשתמשים ממודעות ממומנות קפצו ישירות לעמודי מוצר, תוך עקיפת הקטלוג, והמירו פי שלושה יותר ממשתמשים אורגניים. לאחר חלוקה מחדש של התקציב, שיעור ההמרה עלה ב-20%. כלי זה ממחיש כל מעבר בין עמודים, ערוצים או שלבים. ללא ויזואליזציה כזו, אי אפשר לראות בדיוק היכן אתם מאבדים תנועה.
למה משפכים סטנדרטיים לא מציגים את התמונה המלאה
דוחות משפך סטנדרטיים מראים המרה בכל שלב אך לא מראים מאיפה מגיעים המשתמשים בעלי הערך הגבוה ביותר או לאן הם הולכים. דיאגרמת Sankey פותרת זאת על ידי הצגת כל הזרימות בין צמתים. לדוגמה, ניתן לראות שמשתמשים ממודעות ממומנות הולכים לעיתים קרובות ישירות לעמודי מוצר, תוך עקיפת הקטלוג, ומבצעים רכישות פי שלושה יותר ממשתמשים אורגניים. זה מאפשר לחלק מחדש את התקציב ולהגדיל ROI. דיאגרמות Sankey יעילות פי 3 ממשפכים סטנדרטיים בזיהוי צווארי בקבוק.
כיצד דיאגרמת Sankey משפרת את האנליטיקה
ה-Sankey עונה על שאלות שאינן נראות בטבלאות: מאיפה מגיעים משתמשים בעלי שיעור המרה גבוה, איזה מסלול מוביל ל-LTV מקסימלי, היכן אובדת הכי הרבה תנועה. אנו משתמשים ב-drill-down — לחיצה על צומת חושפת את המבנה הפנימי שלו, ומאפשרת חקירה מעמיקה ללא עצירה. באנליטיקת מוצר, ה-Sankey מראה אילו שילובי ערוצים (אורגני → מוצר → עגלה) מובילים לרכישה ואילו מובילים לנטישה. עבור נתונים מחזוריים (משתמשים בלולאות), אנו משתמשים ב-d3-sankey-circular.
מה מספק Drill-Down
Drill-down מאפשר לפרט את הצומת הנבחר על ידי חשיפת המבנה הפנימי שלו. לדוגמה, לחיצה על צומת 'עגלה' מראה מאילו מקורות הגיעו המשתמשים ואילו פעולות ביצעו לאחר מכן. זה שימושי במיוחד לניתוח מעמיק של משפכים עם שלבים רבים.
השוואה בין משפך סטנדרטי לדיאגרמת Sankey
| מאפיין | משפך סטנדרטי | דיאגרמת Sankey |
|---|---|---|
| מספר המסלולים המוצגים | רק שלבים רציפים | כל המסלולים האפשריים |
| ויזואליזציה של נטישות | לא מציג | מציג רוחב זרימה |
| אינטראקטיביות | מוגבלת | Drill-down, סינון, tooltip |
| קריאות עם 100+ צמתים | בלתי אפשרי | עובד עם אופטימיזציה |
| השוואת מקורות תנועה | דורש דוחות נפרדים | מפה אחידה אחת |
יישום טכני של Sankey על React
אנו משתמשים בטכנולוגיות מודרניות: React 18, TypeScript, d3-sankey. זה מבטיח רינדור חלק גם עם 10,000+ חיבורים – לפי התיעוד הרשמי של d3-sankey.
התקנה ותלויות
npm install d3-sankey d3 npm install --save-dev @types/d3-sankey מבנה נתונים
הנתונים עבור ה-Sankey מורכבים מצמתים וקישורים. כל קישור מכיל מקור, יעד וערך. דוגמה למשפך מסחר אלקטרוני:
interface SankeyNode {
id: string;
label: string;
color?: string;
}
interface SankeyLink {
source: string; // id узла-источника
target: string; // id узла-цели
value: number; // объём потока
}
interface SankeyData {
nodes: SankeyNode[];
links: SankeyLink[];
}
// Пример: воронка e-commerce
const data: SankeyData = {
nodes: [
{ id: 'organic', label: 'Органика' },
{ id: 'paid', label: 'Платная реклама' },
{ id: 'direct', label: 'Прямые' },
{ id: 'catalog', label: 'Каталог' },
{ id: 'product', label: 'Карточка товара' },
{ id: 'cart', label: 'Корзина' },
{ id: 'checkout', label: 'Оформление' },
{ id: 'purchase', label: 'Покупка' },
{ id: 'exit', label: 'Выход' },
],
links: [
{ source: 'organic', target: 'catalog', value: 4200 },
{ source: 'organic', target: 'product', value: 1800 },
{ source: 'paid', target: 'catalog', value: 2100 },
{ source: 'paid', target: 'product', value: 3400 },
{ source: 'direct', target: 'catalog', value: 900 },
{ source: 'catalog', target: 'product', value: 5600 },
{ source: 'catalog', target: 'exit', value: 3100 },
{ source: 'product', target: 'cart', value: 2900 },
{ source: 'product', target: 'exit', value: 4800 },
{ source: 'cart', target: 'checkout', value: 1600 },
{ source: 'cart', target: 'exit', value: 1300 },
{ source: 'checkout', target: 'purchase', value: 1100 },
{ source: 'checkout', target: 'exit', value: 500 },
],
}; קומפוננטה עם Tooltip ואינטראקטיביות
קומפוננטת ה-React שלנו מרנדרת SVG באמצעות d3. היא כוללת:
- נתיבים מעוגלים חלקים
- Tooltip בעת ריחוף מעל צמתים או קישורים
- קידוד צבע לפי צומת (סולם Tableau10)
- רוחב וגובה אדפטיביים
import { useEffect, useRef } from 'react';
import * as d3 from 'd3';
import { sankey, sankeyLinkHorizontal, sankeyLeft } from 'd3-sankey';
export function SankeyDiagram({ data, width = 800, height = 500 }: { data: SankeyData; width?: number; height?: number }) {
const svgRef = useRef<SVGSVGElement>(null);
const margin = { top: 20, right: 20, bottom: 20, left: 20 };
useEffect(() => {
if (!svgRef.current) return;
const svg = d3.select(svgRef.current);
svg.selectAll('*').remove();
const iw = width - margin.left - margin.right;
const ih = height - margin.top - margin.bottom;
// Подготовка данных для d3-sankey
const nodeMap = new Map(data.nodes.map((n, i) => [n.id, { ...n, index: i }]));
const sankeyData = {
nodes: data.nodes.map(n => ({ ...n })),
links: data.links.map(l => ({
source: data.nodes.findIndex(n => n.id === l.source),
target: data.nodes.findIndex(n => n.id === l.target),
value: l.value,
})),
};
const sankeyLayout = sankey()
.nodeWidth(20)
.nodePadding(12)
.nodeAlign(sankeyLeft)
.extent([[0, 0], [iw, ih]]);
const { nodes, links } = sankeyLayout(sankeyData as any);
const colorScale = d3.scaleOrdinal(d3.schemeTableau10);
const g = svg.append('g').attr('transform', `translate(${margin.left},${margin.top})`);
// Tooltip
const tooltip = d3.select('body').append('div')
.style('position', 'absolute')
.style('display', 'none')
.style('background', 'rgba(0,0,0,0.8)')
.style('color', '#fff')
.style('padding', '8px 12px')
.style('border-radius', '4px')
.style('font-size', '13px')
.style('pointer-events', 'none');
// Links
g.append('g')
.selectAll('.link')
.data(links)
.join('path')
.attr('class', 'link')
.attr('d', sankeyLinkHorizontal())
.attr('fill', 'none')
.attr('stroke', (d: any) => colorScale(String(d.source.index)))
.attr('stroke-width', (d: any) => Math.max(1, d.width))
.attr('stroke-opacity', 0.4)
.on('mouseover', (event, d: any) => {
d3.select(event.currentTarget).attr('stroke-opacity', 0.7);
tooltip
.style('display', 'block')
.style('left', `${event.pageX + 12}px`)
.style('top', `${event.pageY - 28}px`)
.html(`<strong>${d.source.label} → ${d.target.label}</strong><br/>${d3.format(',.0f')(d.value)} пользователей`);
})
.on('mouseout', (event) => {
d3.select(event.currentTarget).attr('stroke-opacity', 0.4);
tooltip.style('display', 'none');
});
// Nodes
const nodeG = g.append('g')
.selectAll('.node')
.data(nodes)
.join('g')
.attr('class', 'node');
nodeG.append('rect')
.attr('x', (d: any) => d.x0)
.attr('y', (d: any) => d.y0)
.attr('width', (d: any) => d.x1 - d.x0)
.attr('height', (d: any) => Math.max(1, d.y1 - d.y0))
.attr('fill', (d: any) => colorScale(String(d.index)))
.attr('rx', 3)
.on('mouseover', (event, d: any) => {
tooltip
.style('display', 'block')
.style('left', `${event.pageX + 12}px`)
.style('top', `${event.pageY - 28}px`)
.html(`<strong>${d.label}</strong><br/>Объём: ${d3.format(',.0f')(d.value)}`);
})
.on('mouseout', () => tooltip.style('display', 'none'));
// Labels
nodeG.append('text')
.attr('x', (d: any) => d.x0 < iw / 2 ? d.x1 + 6 : d.x0 - 6)
.attr('y', (d: any) => (d.y0 + d.y1) / 2)
.attr('dy', '0.35em')
.attr('text-anchor', (d: any) => d.x0 < iw / 2 ? 'start' : 'end')
.attr('font-size', 12)
.attr('fill', '#374151')
.text((d: any) => d.label);
return () => {
tooltip.remove();
};
}, [data, width, height]);
return <svg ref={svgRef} width={width} height={height} />;
} הכנת נתונים: צבירת SQL
הנתונים עבור Sankey נצברים בדרך כלל מזרם אירועים. דוגמה לשאילתת SQL למשפך אתר (מעברי עמודים רציפים בתוך סשן):
WITH ranked_events AS (
SELECT session_id, page_type, LAG(page_type) OVER (PARTITION BY session_id ORDER BY created_at) AS prev_page_type, ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY created_at) AS step
FROM page_views
WHERE created_at > NOW() - INTERVAL '30 days'
)
SELECT COALESCE(prev_page_type, 'entry') AS source, page_type AS target, COUNT(*) AS value
FROM ranked_events
WHERE prev_page_type IS NOT NULL OR step = 1
GROUP BY 1, 2
HAVING COUNT(*) > 50
ORDER BY value DESC;שאילתה זו מפיקה טבלת מעברים עם ספירות משתמשים. עבור נפחי נתונים גדולים, אנו משתמשים בצבירת נתונים מוקדמת עם Materialized Views או טריגרים.
הגדרת פריסה: איזה אלגוריתם לבחור?
npm install d3-sankey d3 npm install --save-dev @types/d3-sankey תומך במספר אלגוריתמי יישור צמתים. הבחירה משפיעה על קריאות הדיאגרמה.
| אלגוריתם | תיאור | מקרה שימוש |
|---|---|---|
| sankeyLeft | צמתים מיושרים לשמאל הרמה | משפכים עם סדר שלבים קבוע |
| sankeyRight | יישור לימין | גרפים עם צמתי עלה משמאל |
| sankeyCenter | יישור למרכז הגרף | גרפים א-ציקליים ללא כיוון ברור |
| sankeyJustify | צמתי עלה נדחפים לימין | מקרה כללי |
עבור נתונים מחזוריים, אנו משתמשים ב-interface SankeyNode { id: string; label: string; color?: string; } interface SankeyLink { source: string; // id узла-источника target: string; // id узла-цели value: number; // объём потока } interface SankeyData { nodes: SankeyNode[]; links: SankeyLink[]; } // Пример: воронка e-commerce const data: SankeyData = { nodes: [ { id: 'organic', label: 'Органика' }, { id: 'paid', label: 'Платная реклама' }, { id: 'direct', label: 'Прямые' }, { id: 'catalog', label: 'Каталог' }, { id: 'product', label: 'Карточка товара' }, { id: 'cart', label: 'Корзина' }, { id: 'checkout', label: 'Оформление' }, { id: 'purchase', label: 'Покупка' }, { id: 'exit', label: 'Выход' }, ], links: [ { source: 'organic', target: 'catalog', value: 4200 }, { source: 'organic', target: 'product', value: 1800 }, { source: 'paid', target: 'catalog', value: 2100 }, { source: 'paid', target: 'product', value: 3400 }, { source: 'direct', target: 'catalog', value: 900 }, { source: 'catalog', target: 'product', value: 5600 }, { source: 'catalog', target: 'exit', value: 3100 }, { source: 'product', target: 'cart', value: 2900 }, { source: 'product', target: 'exit', value: 4800 }, { source: 'cart', target: 'checkout', value: 1600 }, { source: 'cart', target: 'exit', value: 1300 }, { source: 'checkout', target: 'purchase', value: 1100 }, { source: 'checkout', target: 'exit', value: 500 }, ], }; או שוברים מחזורים מראש.
מה כלול בעבודה
- אנליטיקה: חקר מבנה הנתונים שלך, זיהוי מדדים מרכזיים ונקודות אינטגרציה.
- עיצוב: פיתוח פריסה, בחירת אלגוריתם פריסה, אב-טיפוס של אינטראקציות.
- יישום: קידוד הקומפוננטה ב-React/TypeScript, הגדרת backend לצבירת נתונים.
- תיעוד: תיאור ה-API של הקומפוננטה, הוראות שימוש והתאמה אישית.
- בדיקות: אימות על נתונים אמיתיים, בדיקות עומס (עד 100,000 קישורים), אופטימיזציה.
- פריסה: אינטגרציה עם הממשק שלך, הגדרת build ופריסה אוטומטיים.
- הדרכה: סמינר מקוון לצוות שלך על שימוש והרחבת הדיאגרמה.
- תמיכה: 30 ימים של ייעוץ חינם ותיקוני באגים לאחר הפריסה.
תהליך הפיתוח ולוח זמנים
הצוות שלנו מיישם את דיאגרמת Sankey במפתח מלא. ניסיון עם למעלה מ-50 פרויקטים.
- אנליטיקה: חקר מבנה הנתונים שלך, הגדרת מדדים מרכזיים.
- עיצוב: פיתוח פריסה, בחירת אלגוריתם פריסה, תכנון אינטראקציות.
- יישום: קידוד הקומפוננטה ב-React/TypeScript, הגדרת צבירת נתונים ב-backend.
- בדיקות: אימות על נתונים אמיתיים, אופטימיזציה של ביצועים.
- פריסה: אינטגרציה עם הממשק שלך, פריסה על השרת שלך או בענן.
- תמיכה: 30 ימים של שיפורים חינם וייעוץ.
גרסה בסיסית עם tooltip ואינטראקציות – 2–3 ימים (עלות החל מ-$2,000). גרסה מורחבת עם drill-down, סינון וייצוא – 5–7 ימים (עלות החל מ-$5,000).
תוצאות היישום
לאחר יישום דיאגרמת Sankey, הלקוחות שלנו רואים עלייה בשיעורי המרה של 15–30% והפחתה ב-CPA של 20–40% על ידי זיהוי צווארי בקבוק. לדוגמה, לקוח חסך $50,000 בשנה על ידי חלוקה מחדש של הוצאות הפרסום. אנו מספקים אחריות קוד ל-6 חודשים ותיעוד מלא. תרשים אינטראקטיבי זה הוא כלי עוצמתי לאופטימיזציית המרות. צרו קשר כדי להזמין דיאגרמת Sankey מותאמת אישית לאתר שלכם. קבלו ייעוץ ממהנדס עוד היום.







