گذاشتن رویداد روی سایت و اپ خودتان
از سؤال کسبوکار تا خط کدی که روی صفحه مینشیند: چه رویدادهایی لازم دارید، کجای کد صدایشان بزنید، و چطور مطمئن شوید رسیدهاند.
این صفحه فرض میکند سایت یا اپی دارید که کار میکند و هنوز هیچ رویدادی از آن بیرون نمیآید. تعریف رویداد میگوید کد ما با چیزی که میفرستید چه میکند و فرهنگنامهٔ رویدادها فهرست آمادهٔ هر صنف را دارد. این صفحه کار سومی میکند: از سؤالی که میخواهید جوابش را بدانید شروع میکند و به همان خط کدی میرسد که باید روی صفحهٔ شما بنشیند.
پیش از هر چیز، چیزی که خیلیها انتظارش را دارند و وجود ندارد: در سگمنتیک رویداد از قبل ثبت نمیشود. هیچ فرمی، هیچ endpointی و هیچ صفحهای برای «ساختن رویداد» نیست. هر نامی که بفرستید پذیرفته میشود و رویداد در همان لحظهٔ اولین ارسال وجود پیدا میکند. کاری که واقعا انجام میدهید انتخاب نام و ویژگیهاست، و بعد گذاشتن یک فراخوانی در جای درست کد خودتان.
این آزادی دو طرف دارد. طرف خوبش این است که برای اضافه کردن یک رویداد تازه به هیچکس احتیاج ندارید. طرف بدش این است که هیچ نگهبانی جلوی نام غلط را نمیگیرد، و نام غلط بعدا اصلاح نمیشود. برای همین ترتیب این صفحه از فهرست شروع میشود، نه از کد.
از سؤال شروع کنید، نه از صفحه
وسوسهٔ اول این است که آدم صفحههای سایتش را مرور کند و هرچه میشود کلیک کرد را بفرستد. نتیجهاش هشتاد نام است که هیچکدام به هیچ تصمیمی وصل نیست.
راه درست برعکس است: سه تا پنج سؤال بنویسید که اگر جوابشان را داشتید کاری میکردید. بعد برای هر سؤال بپرسید کدام رویداد جوابش را میدهد.
| سؤالی که میپرسید | کاری که با جوابش میکنید | رویدادی که لازم دارید |
|---|---|---|
| چه کسانی سبد را رها کردند | برایشان یادآوری میفرستم | cart_updated و order_completed |
| کدام بنر صفحهٔ اصلی کار میکند | بنر ضعیف را عوض میکنم | banner_viewed و banner_clicked |
| چه کسانی محصول گران را دیدند و نخریدند | تخفیف هدفمند میدهم | product_viewed با price |
| چه کسی سی روز است برنگشته | کمپین بازگشت میسازم | هر رویدادی، تاریخ آخرین بازدید کافی است |
سطر آخر عمدا آنجاست: بعضی سؤالها هیچ رویداد تازهای لازم ندارند. قبل از اضافه کردن نام جدید، ببینید چیزی که همین حالا میفرستید جواب را نمیدهد.
فهرست را روی کاغذ ببندید
قبل از باز کردن ویرایشگر، یک جدول با همین چهار ستون پر کنید. این جدول چیزی است که به توسعهدهنده میدهید و بعدا هم سند مرجع خودتان است.
| نام رویداد | کی صدا زده میشود | ویژگیها | چه کسی میفرستد |
|---|---|---|---|
banner_viewed | وقتی بنر واقعا وارد کادر دید شد | banner_id, slot | مرورگر |
banner_clicked | کلیک روی بنر | banner_id, slot, destination | مرورگر |
product_viewed | باز شدن صفحهٔ محصول | product_id, category, price | مرورگر |
checkout_started | ورود به صفحهٔ پرداخت | cart_value, item_count | مرورگر |
order_completed | تایید نهایی پرداخت | order_id, revenue, currency | سرور |
ستون آخر مهمترین ستون است و معمولا از قلم میافتد. جوابش در بخش چیزهایی که مرورگر نباید بگوید است.
ستون «کی صدا زده میشود» را با فعل بنویسید نه با اسم صفحه. «وقتی بنر وارد کادر دید شد» یک جملهٔ قابل پیادهسازی است؛ «در صفحهٔ اصلی» نیست، چون معلوم نمیکند لحظهٔ ارسال کجاست.
چند تا رویداد کافی است
بین پنج تا پانزده تا، برای شروع.
سقف فنیای در کار نیست و هیچکس شمارشتان نمیکند. محدودیت جای دیگری است: کاتالوگ رویدادها در پنل، پانصد نام پرحجمتر در نود روز گذشته را نشان میدهد. اگر نامهای بیمصرف زیاد شوند، رویدادهای واقعی از این فهرست میافتند بیرون و در سگمنتساز قابل انتخاب نمیمانند. یک بار برای یک مشتری واقعی همین اتفاق افتاد، با نامهایی که شکل آدرس داشتند؛ شرحش در وقتی نام رویداد یک آدرس است هست.
محدودیت دوم انسانی است. رویدادی که هیچ سگمنت، هیچ گزارش و هیچ سناریویی از آن استفاده نمیکند، رویدادی است که شش ماه بعد کسی نمیداند چرا فرستاده میشود و جرئت هم نمیکند حذفش کند.
کم شروع کنید. اضافه کردن یک رویداد جدید در هر لحظه ممکن است و هیچ هزینهای ندارد. برداشتن یک نام غلط از تاریخچه ممکن نیست.
نام گذاشتن روی رویداد خودتان
سرور فقط دو چیز را چک میکند: نام از ۱۲۸ بایت بلندتر نباشد و کاراکتر کنترلی نداشته باشد. نه حروف را کوچک میکند، نه فاصله را به زیرخط تبدیل میکند، نه هیچ الگویی را اجبار میکند. قاعدهٔ کامل در قاعدهٔ نامگذاری است.
یعنی هر چیزی که در ادامه میآید قرارداد است، نه اجبار. ولی قراردادی است که نامهای استاندارد خود پلتفرم از آن پیروی میکنند، و همسو ماندن با آن یعنی فهرست رویدادهایتان مرتب میماند.
| قاعده | بنویسید | ننویسید |
|---|---|---|
| اسم شیء اول، بعد فعل گذشته | banner_clicked | click_banner |
| حروف کوچک و زیرخط | wallet_topped_up | WalletToppedUp |
| هیچ متغیری داخل نام نباشد | banner_clicked با banner_id | banner_nowruz_hero_clicked |
| یک نام برای یک اتفاق | product_viewed | product_view و productViewed کنار هم |
سطر دوم و چهارم یک تلهٔ مشترک دارند: چون سرور حروف را کوچک نمیکند، Banner_Clicked و banner_clicked تا ابد دو رویداد جداگانهاند. هیچ خطایی هم نمیگیرید. فقط یک روز میبینید عددها نصف شدهاند.
سطر سوم پرهزینهترین است. نامی که داخلش شناسه یا مقدار متغیر دارد، به ازای هر مقدار یک رویداد تازه میسازد و همان چیزی است که کاتالوگ را پر میکند.
یک نام، چند جای مختلف
بنر شما هم در صفحهٔ اصلی هست، هم بالای صفحهٔ دستهبندی، هم داخل ایمیل. سه نام نسازید.
یک نام بگذارید و جای وقوع را در یک ویژگی بفرستید:
Segmentic.track("banner_clicked", {
banner_id: "nowruz_hero",
slot: "homepage_top"
});
دلیلش این است که سؤالهای شما هر دو شکل را میخواهند. «کل کلیک روی این بنر چقدر بود» با یک نام جواب میگیرد، و «کدام جایگاه بهتر کار میکند» با شکستن روی همان ویژگی. اگر سه نام بسازید، سؤال اول دیگر جواب ساده ندارد.
قاعدهٔ کلی: چیزی که میخواهید روی آن جمع بزنید نام است، و چیزی که میخواهید روی آن بشکنید ویژگی است.
کجای کد صدایش بزنید
اینجا جایی است که پیادهسازیها خراب میشوند. رویداد در لحظهٔ غلط، بدتر از رویداد نفرستادن است، چون عدد میدهد و عددش غلط است.
| اتفاق | کجا صدا بزنید | چرا نه جای دیگر |
|---|---|---|
| کلیک روی لینک یا دکمه | یک listener روی document با closest | بنرها معمولا بعدا یا داخل اسلایدر رندر میشوند و listener مستقیم به آنها نمیرسد |
| ثبت فرم | بعد از پاسخ موفق سرور | روی submit رویداد را برای فرمهایی هم میفرستید که رد شدهاند |
| دیده شدن یک بخش | با IntersectionObserver | روی لود صفحه یعنی هر بازدیدکنندهای که تا پایین اسکرول نکرده هم شمرده میشود |
| رفتن به صفحهٔ دیگر در اپ تکصفحهای | خود SDK با autoPageView | فراخوانی دستی در useEffect روی هر رندر دوباره میفرستد |
| پرداخت موفق | از سرور | مرورگر خبر ندارد پول واقعا نشسته است یا نه |
نگرانی رایج بعدی این است که کاربر روی لینک کلیک میکند و صفحه عوض میشود، پس رویداد فرصت رفتن پیدا نمیکند. این یکی حل شده است: SDK وب بهصورت پیشفرض هر بیست پیام یا هر ده ثانیه صف را خالی میکند و علاوه بر آن روی pagehide و مخفی شدن صفحه با sendBeacon میفرستد، که کندن صفحه را دوام میآورد. جزئیاتش در صف آفلاین است.
یک مثال کامل: کلیک روی بنر
فرض کنید سؤالتان این است: «کدام بنر صفحهٔ اصلی کار میکند و چه کسانی رویش کلیک کردند.»
اول SDK را نصب کنید. کلید نوشتن را از صفحهٔ «اتصال» در پنل بردارید:
<script src="https://in.segmentic.net/sdk/segmentic.js"></script>
<script>
Segmentic.init({
writeKey: "wk_...",
apiHost: "https://in.segmentic.net"
});
</script>
بعد به خود بنرها یک نشانه بدهید. اینکه شناسه در HTML بنشیند یعنی برای بنر بعدی لازم نیست کسی جاوااسکریپت را دست بزند:
<a href="/campaign/nowruz"
data-banner="nowruz_hero"
data-slot="homepage_top">
<img src="/banners/nowruz.jpg" alt="جشنوارهٔ نوروز">
</a>
بعد یک listener، یک بار، برای همهٔ بنرهای سایت:
document.addEventListener("click", function (e) {
var el = e.target.closest("[data-banner]");
if (!el) return;
Segmentic.track("banner_clicked", {
banner_id: el.dataset.banner,
slot: el.dataset.slot,
destination: el.getAttribute("href")
});
});
و اگر نرخ کلیک میخواهید، دیده شدن را هم بفرستید. once مهم است، وگرنه هر بار که بنر از کادر دید بیرون و تو برود دوباره شمرده میشود:
var seen = new WeakSet();
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (!entry.isIntersecting || seen.has(entry.target)) return;
seen.add(entry.target);
var el = entry.target;
Segmentic.track("banner_viewed", {
banner_id: el.dataset.banner,
slot: el.dataset.slot
});
});
}, { threshold: 0.5 });
document.querySelectorAll("[data-banner]").forEach(function (el) {
io.observe(el);
});
همین. هیچ ثبتی، هیچ migrationی و هیچ تنظیمی در پنل لازم نیست. رویداد banner_clicked از اولین کلیک وجود دارد.
داخل اپ موبایل
نامها را عوض نکنید. همان banner_clicked که وب میفرستد، اپ هم باید بفرستد. banner_clicked_android نسازید، چون آنوقت هر سؤالی دو بار پرسیده میشود و هر گزارشی دو ستون دارد.
پلتفرم را خود SDK در context میگذارد و در گزارشها قابل شکستن است، پس لازم نیست در نام یا ویژگی تکرارش کنید.
نصب و متدها در SDK اندروید است. جای فراخوانی همان منطق بالا را دارد: در لحظهٔ تعامل واقعی، نه در onCreate و نه در سازندهٔ ویو.
چیزهایی که مرورگر نباید بگوید
کلید نوشتن عمدا عمومی است. داخل صفحهٔ شماست و هر کسی میتواند ببیندش و با آن رویداد بفرستد. برای banner_clicked این اهمیتی ندارد. برای عددی که در گزارش درآمد مینشیند اهمیت دارد.
پس اینها را از بکاند خودتان بفرستید نه از مرورگر:
- هر رویدادی که مبلغ دارد، بهخصوص
order_completedوrevenueآن - هر چیزی که وضعیت رسمی است: ارسال شد، مرجوع شد، اشتراک تمدید شد
- هر چیزی که مرورگر اصلا از آن خبر ندارد، مثل تایید درگاه پرداخت که به صورت callback به سرور شما میآید
دو در برای این کار هست و تفاوتشان در سرور به سرور کامل باز شده. کوتاهش: POST /v1/batch روی https://in.segmentic.net با همان کلید نوشتن، یا POST /v1/events روی https://api.segmentic.net با کلید محرمانهٔ sk_seg_.
در دوم دو تفاوت بیصدا دارد: تکراریها را حذف نمیکند، پس یک retry ساده در کد شما رویداد را دو بار میسازد؛ و پنجرهٔ زمانش ثابت سی روز است. برای انتقال تاریخچه از این در استفاده نکنید.
اگر همان رویداد را هم از مرورگر و هم از سرور بفرستید، دو تا میشود. یکی را انتخاب کنید. برای رویدادهای پولی، همیشه سرور.
وصل کردن رویداد به یک آدم
رویدادی که فرستادید تا اینجا فقط anonymous_id دارد. یعنی میدانید یک مرورگر روی بنر کلیک کرد، ولی نمیدانید کی بود و نمیتوانید برایش ایمیل بفرستید.
identify همان چیزی است که این را وصل میکند. هر جا کاربر را میشناسید صدایش بزنید: بعد از ورود، بعد از ثبتنام، یا روی هر صفحهای اگر نشست باز دارید.
Segmentic.identify("u_8842", {
email: "ali@example.com",
phone: "09121234567"
});
نکتهٔ مهم: لازم نیست identify قبل از کلیک اتفاق بیفتد. SDK در اولین identify خودش یک alias هم میفرستد، پس تاریخچهٔ ناشناس همان مرورگر به پرونده وصل میشود. اگر این کار نمیشد، هر قیفی که از مرز ورود رد شود عدد غلط میداد.
روی خروج از حساب Segmentic.reset() را صدا بزنید، وگرنه رویدادهای نفر بعدی روی همان دستگاه به پروندهٔ نفر قبلی میچسبد. حالتهای دشوارتر، مثل دستگاه مشترک، در هویت است.
بررسی کنید هر کدام واقعا رسیده
این مرحله را رد نکنید. رویدادی که یادتان رفته چک کنید، معمولا همان است که سه ماه بعد معلوم میشود هیچوقت نیامده.
مرحلهٔ اول، همان لحظه: صفحهٔ «دیباگ» را در پنل باز بگذارید، در تب دیگری روی بنر کلیک کنید و ببینید ظرف چند ثانیه میآید. اگر نیامد مشکل از نصب است نه از نام رویداد. یک نکته: ارسال دستهای در این صفحه ضبط نمیشود، پس برای آزمایش از فراخوانی تکی استفاده کنید.
مرحلهٔ دوم، چند دقیقه بعد: صفحهٔ «داده» را باز کنید. رویداد باید با حجمش و فهرست ویژگیهایش آنجا باشد. اگر نام هست ولی ویژگیای که انتظار داشتید نیست، یعنی مقدارش null یا خالی بوده است.
مرحلهٔ سوم، همانجا: برچسب فارسی رویداد را بگذارید. «کلیک روی بنر» برای کسی که سگمنت میسازد خواناتر از banner_clicked است. برچسب فقط نمایشی است و نام ذخیرهشده هیچوقت عوض نمیشود.
جدول ingest_warnings وجود دارد ولی چیزی در آن نوشته نمیشود. هشدارها فقط در بدنهٔ پاسخ همان درخواست هستند، پس اگر ارسال از سرور میکنید، آن پاسخ را لاگ کنید. راههای دیدنش در دیدن اینکه واقعا چه رسید.
چکلیست پیش از انتشار
- هر رویدادی که در فهرست نوشتید یک بار در صفحهٔ دیباگ دیده شده است.
- هیچ نامی متغیر داخلش ندارد، و همه با یک الگوی حروف نوشته شدهاند.
- شناسهها رشتهاند و عددها عدد، نه رشتهٔ عددی. قاعدهاش در یک ویژگی چه چیزی میتواند نگه دارد است.
revenueفقط روی رویدادهای واقعا پولی نشسته است. روی هر رویدادی که باشد به ارزش عمر مشتری اضافه میشود، حتی رویcart_viewed. شرحش در درآمد.identifyجایی صدا زده میشود که کاربر شناخته میشود، وresetروی خروج.- رویدادهای پولی از سرور میآیند، نه از مرورگر.
- هیچ رویدادی دو بار، یک بار از مرورگر و یک بار از سرور، فرستاده نمیشود.
- برچسب فارسی هر رویداد در صفحهٔ «داده» گذاشته شده است.
اشتباههای رایج
| اشتباه | چه چیزی خراب میشود | به جایش |
|---|---|---|
| نام حاوی شناسه یا آدرس | کاتالوگ پر میشود و رویدادهای واقعی از فهرست پانصدتایی میافتند | شناسه را ویژگی کنید |
رویداد روی submit فرم | فرمهای ردشده هم شمرده میشوند | بعد از پاسخ موفق |
revenue روی رویداد غیرپولی | ارزش عمر مشتری بیسروصدا باد میکند | فقط روی خرید |
فرستادن url و referrer بهعنوان ویژگی | جای ویژگی را میگیرد بیآنکه چیزی اضافه کند | SDK خودش در context میفرستد |
| مقدار فارسی برای دستهبندیها | فیلتر روی املای مختلف میشکند | یک زبان برای مقادیر، برچسب را در پنل بگذارید |
identify فقط در صفحهٔ ورود | کسی که با نشست باز برمیگردد ناشناس میماند | هر جا نشست معتبر است |
نبود reset روی خروج | رویدادهای دو نفر روی یک پرونده جمع میشود | reset در مسیر خروج |
| رویداد هم از مرورگر هم از سرور | عددها دو برابر میشوند | یکی را انتخاب کنید |
بعد چه بخوانید
- تعریف رویداد برای قاعدههای دقیق نام، ویژگی و سقفها.
- فرهنگنامهٔ رویدادها اگر فروشگاه، فینتک، سفر یا آموزش دارید و فهرست آماده میخواهید.
- هویت اگر کاربر مهمان دارید که بعدا وارد میشود.
- SDK وب برای همهٔ متدها و تنظیمات.
- سرور به سرور برای انتخاب بین دو در.
- سگمنتها وقتی رویدادها رسیدند و میخواهید رویشان سگمنت بسازید.
- کاتالوگ محصولات اگر فروشگاه دارید و میخواهید در پیامها محصول پیشنهاد بدهید.