مفهومها: رویداد، پروفایل، سگمنت، کمپین، سناریو
ده مفهومی که بقیهٔ مستندات روی آنها سوار است، هرکدام در یک بند، با نامی که در پنل و در API یکی است.
این صفحه ده واژه است، نه بیشتر. هر کدام یک چیز مشخص در محصولاند و اسمشان در پنل، در API و در این مستندات یکی است. اگر یک عامل هوش مصنوعی قرار است با این سرویس کار کند، این اولین صفحهای است که باید بخواند.
هرجا این صفحه میگوید چیزی «نیست»، یعنی وجود ندارد؛ نه اینکه هنوز مستند نشده باشد.
| مفهوم | در پنل | روی سیم و در انگلیسی |
|---|---|---|
| رویداد | رویداد | event |
| پرونده | پرونده، و در منو «کاربران» | profile |
| ویژگی | ویژگی | trait |
| سگمنت | سگمنت | segment |
| مخاطب | مخاطب | audience |
| کمپین | کمپین | campaign |
| سناریو | سناریو | journey |
| کانال | کانال | channel |
| کلید نوشتن | کلید نوشتن | write key |
| کلید API | کلیدهای API | API key |
رویداد
رویداد یک اتفاق است که یک بار افتاده، در یک لحظه، برای یک هویت. نامی دارد، زمانی دارد، و میتواند ویژگیهایی همراهش بیاید. پنج نوع پیام وجود دارد و مسیر درخواست تعیین میکند کدام است: track، identify، page، screen و alias. دو جا خودتان نوع را مینویسید: آیتمهای POST /v1/batch روی میزبان ورود داده، و آیتمهای POST /v1/events روی میزبان مدیریتی. در هر دو، نوعی که نشناسیم رویداد را با unknown_type رد میکند.
نام رویداد بعد از نرمالسازی فارسی حداکثر ۱۲۸ بایت است و نویسهٔ کنترلی نمیپذیرد. هیچ فهرست مجاز، هیچ یکسانسازی حروف بزرگ و کوچک و هیچ اجبار به snake_case وجود ندارد. نام فارسی هم پذیرفته میشود. نتیجهٔ مستقیمش این است که Order Completed و order_completed تا ابد دو رویداد جدا میمانند و هیچ خطایی هم نمیگیرید. یازده نام استاندارد وجود دارد که قیفها و سناریوهای آماده روی آنها سوارند: product_viewed، product_added_to_cart، product_removed_from_cart، cart_viewed، checkout_started، order_completed، order_refunded، order_cancelled، searched، signed_up و signed_in.
ویژگیهای رویداد حداکثر ۲۵۶ تا نگه داشته میشوند. کلیدها نرمال میشوند: فاصله و نقطه و خط تیره به زیرخط تبدیل میشوند. مقدارها دو جا مینشینند، یک نقشهٔ رشتهای و یک نقشهٔ عددی، چون نقشه در انبار داده باید همنوع باشد. مقدار null ذخیره نمیشود، چون «تنظیم نشده» با «رشتهٔ خالی» یکی نیست و اگر یکی میشد، شرط «تنظیم نشده» غلط جواب میداد.
رویداد چه چیزی نیست: رویداد وضعیت نیست. «کاربر اکنون اشتراک طلایی دارد» ویژگی است نه رویداد؛ «کاربر اشتراک طلایی خرید» رویداد است. رویداد ذخیرهشده هم قابل ویرایش نیست. هیچ endpointی برای ویرایش یا حذف یک رویداد وجود ندارد و سه چیز سطر را برمیدارد: سیاست نگهداری تنانت شما، TTL ۴۰۰ روزهٔ خود جدول events، و پاکسازی دادهٔ یک شخص که درخواست نامش را میبرد.
پرونده و ویژگی
پرونده یک ردیف است بهازای هر user_id در هر حساب، که از تاشدن رویدادهای همان کاربر ساخته میشود. در منوی پنل این بخش «کاربران» نام دارد و خود صفحه از واژهٔ «پرونده» استفاده میکند. ویژگی، چیزی است که دربارهٔ آن آدم درست است: ایمیل، شهر، موجودی، تاریخ ثبتنام. ویژگیها با identify میآیند.
چند ویژگی رفتار خاص دارند: email فقط کوچک و trim میشود، phone به E.164 تبدیل میشود و یک phone_operator هم از رویش ساخته میشود، national_id اگر رقم کنترلیاش درست نباشد یکسره کنار گذاشته میشود، و gender به یکی از سه مقدار male، female یا other نگاشته میشود. بقیهٔ ویژگیها آزادند و دو بار نوشته میشوند، یک بار رشته و یک بار عدد. فقط نیمهٔ عددی است که به شرط «بزرگتر از» جواب میدهد؛ این دوبارهنویسی از یک خرابی واقعی درآمد که در آن «موجودی ۱۰۰ یا بیشتر» هیچکس را برنمیگرداند و «کمتر از ۱۰» هر ۱۱۴۹۴۳ پرونده را برمیگرداند، از جمله کسی که موجودیاش ۴۲۸ بود، بدون خطا و بدون هشدار.
نگفتن یک ویژگی یعنی «دست نزن». فرستادن رشتهٔ خالی هم یعنی «دست نزن»، نه «پاکش کن»: مقدار خالی پیش از ساختهشدن رویداد کنار گذاشته میشود و هرگز به پرونده نمیرسد. لایهٔ پرونده قاعدهٔ «پاک کن» را دارد و هیچ مسیر مشتریرویی به آن نمیرسد؛ گرهٔ «تغییر ویژگی» در سناریو هم مقدار خالی را با پیام صریح رد میکند. یعنی راه پشتیبانیشدهای برای پاککردن یک ویژگی وجود ندارد و تنها حذف واقعی، همان مسیر پاککردن دادهٔ شخصی است که کل پرونده را میبرد. پروندهٔ تازه هر سه رضایت ارسال (ایمیل، پیامک، پوش) را روشن شروع میکند، چون پایگاه مشتری که وارد سیستم میشود پیش از این از مسیر خود مشتری رضایت داده و پیشفرض خاموش یعنی اولین کمپین به هیچکس نمیرسد.
پرونده چه چیزی نیست: کاربر ناشناس پرونده ندارد. تا وقتی رویدادی با user_id نیاید، هیچ ردیفی ساخته نمیشود.
هویت
سه شناسه وجود دارد. anonymous_id را SDK میسازد و نگه میدارد. user_id را سامانهٔ ورود خودتان میدهد. previous_id فقط روی پیام alias معنی دارد و عمرش یک پیام است. دستکم یکی از دو تای اول اجباری است، و همان است که کلید پارتیشنبندی میشود تا همهٔ پیامهای یک آدم به ترتیب دیده شوند.
alias تاریخچهٔ ناشناس را به کاربر منتقل نمیکند. کاری که میکند فقط یک چیز است: یک ردیف در نقشهٔ هویت مینویسد که میگوید این شناسهٔ ناشناس متعلق به این کاربر بوده. هیچجا رویدادهای قبلی بازنویسی نمیشوند؛ آن ردیفها تا ابد user_id خالی دارند، و هیچ گزارشی نقشهٔ هویت را join نمیکند. یعنی قیفی که با یک product_viewed ناشناس شروع میشود و با یک order_completed واردشده تمام میشود، این دو را یکی نمیبیند. تنها مصرفکنندهٔ واقعی نقشهٔ هویت، مسیر پاککردن دادهٔ شخصی است، که با آن رویدادهای پیش از ورود همان آدم را هم پیدا و حذف میکند.
روی خروج از حساب reset() را صدا بزنید. اگر نزنید، نفر بعدی روی همان دستگاه شناسهٔ ناشناس نفر قبلی را به ارث میبرد و ردیف نقشهٔ هویت هم جای قبلی را میگیرد. پیامدش این است که اگر بعد از آن نفر اول درخواست حذف داده بدهد، رویدادهای ناشناسش پیدا نمیشوند.
سگمنت
سگمنت شیء ذخیرهشده است: یک فیلتر با نام و شناسه که در پنل میماند و کمپینها و سناریوها به آن ارجاع میدهند. تعریفش SQL نیست، یک درخت JSON است؛ رابط کاربری هیچوقت SQL نمیفرستد و همین مرز است که اجازه میدهد این قابلیت دست بازاریاب باشد.
سه نوع در پایگاه داده تعریف شده است. dynamic پیشفرض است و هیچچیز ذخیرهشدهای ندارد: هر بار که کسی میشمارد یا کمپینی رویش راه میافتد، تعریف دوباره اجرا میشود. static فهرستی است که کسی آدمها را داخلش گذاشته، مثل اکسل یک آژانس یا برندگان یک قرعهکشی، و عضویتش ردیفهای واقعی است. dynamic تعریف میخواهد و static نمیخواهد. نوع سوم، realtime، هم API و هم محدودیت پایگاه داده آن را میپذیرند و هیچ بخشی از سرور آن را پیاده نکرده است. آن را رزروشده بدانید نه کارکننده.
سگمنت چه چیزی نیست: برای سگمنت پویا هیچ عضویت ذخیرهشدهای و هیچ کار زمانبندیشدهٔ بهروزرسانی وجود ندارد. اندازهٔ آخر و زمان محاسبهٔ آخر هم روی هیچ نصب واقعی نوشته نمیشوند، پس کارت سگمنت در کتابخانه همیشه میگوید اندازه محاسبه نشده است. اندازه را همان لحظه که میپرسید حساب میکنند.
مخاطب
مخاطب مجموعهٔ آدمهایی است که یک ارسال به آنها میرسد. در پنل، انتخاب مخاطب یک کمپین همین است. روی API مدیریتی همین واژه اسم دو مسیر بیحافظه است: POST /v1/audiences/validate که فقط میگوید تعریف شما کامپایل میشود یا نه، و POST /v1/audiences/count که تعداد را برمیگرداند. هر دو تعریف را در بدنه میگیرند و هیچچیز ذخیره نمیکنند.
فرق عملی همین است: سگمنت اسم چیزی است که ذخیره میکنید، مخاطب اسم مجموعهٔ آدمهایی است که از یک فیلتر بیرون میآید، چه آن فیلتر ذخیره شده باشد چه نه. هر دو واژه یک زبان فیلتر دارند.
این دوگانگی واژه در خود محصول هم هست و پنهانش نمیکنیم: مسیر شمارش /v1/audiences/count است ولی شیء ذخیرهشده زیر /v1/segments زندگی میکند و پنل به آن «سگمنت» میگوید. روی API مدیریتی مسیر تخمین وجود ندارد. شمارندهٔ زندهٔ پنل POST /v1/segments/estimate را صدا میزند که روی کنترلپلین داشبورد ثبت شده و آن پورت به عمد از اینترنت مسیریابی نمیشود. از سرور خودتان، مسیری که جواب میدهد POST /v1/audiences/count است و بهجای نمونهگیری، دقیق میشمارد.
کمپین
کمپین یک پیام است به یک مخاطب، یک بار یا طبق زمانبندی. وضعیتهایش اینها هستند: draft، scheduled، running، paused، completed، cancelled و failed؛ سه تای آخر پایانیاند و از آنها برگشتی نیست.
روی API مدیریتی میشود کمپینها را فهرست کرد، یکی را خواند، ساخت، فرستاد و برای تأیید ثبت کرد. فهرست، دویست کمپین آخر بر اساس زمان تغییر است و نه بیشتر. این سقف در پاسخ اعلام نمیشود: نه شمارشی، نه has_more، نه مکاننما. حسابی که دویستویکمین کمپین را دارد، آن را روی این سطح نمیبیند و راهی هم برای رفتن جلوتر نیست. همین برای GET /v1/segments هم برقرار است. مکث، ادامه و لغو روی آن سطح وجود ندارند؛ این سه فقط در پنل هستند. اگر یک درخواست تغییر وضعیت با هیچ ردیفی جور درنیاید پاسخ ۴۰۴ است، و سه دلیل جداگانه (مال شما نیست، وجود ندارد، در وضعیت اشتباه است) بهعمد یک جواب میگیرند.
کمپین چه چیزی نیست: کمپین سناریو نیست. کمپین مخاطبش را یک بار حل میکند و از رویش رد میشود؛ سناریو برای هر نفر جداگانه حالت نگه میدارد.
سناریو
سناریو گرافی است که هر کاربر تکتک و با حالت خودش از آن رد میشود. در پنل «سناریو» نام دارد و همین یک نام است: چند صفحهٔ داشبورد قبلاً «ژورنی» مینوشتند، که مثل مفهوم دومی خوانده میشد نه همان مفهوم.
گرهها هشت نوعاند: trigger، wait، condition، switch، split، action، goal و exit. قاعدهٔ ورود یکی از once، every_time یا max_n است. شرط خروج، آدم را همان لحظهای که شرط برقرار شود بیرون میبرد، هرجای گراف که باشد. نسخههای منتشرشده تغییرناپذیرند و تعریف سگمنتها داخلشان کپی میشود نه ارجاع، تا نسخهٔ منتشرشده امروز همان معنایی را بدهد که روز انتشارش داشت.
سناریو چه چیزی نیست: روی API مدیریتی هیچ مسیر سناریویی وجود ندارد. GET /v1/capabilities کلید journeys را زیر features گزارش میکند، ولی آن پرچم فقط میگوید این نصب زیرسیستم سناریو را وصل کرده یا نه؛ حتی وقتی درست است، روی آن میزبان هیچ مسیری را روشن نمیکند. هیچکدام از پرچمهای features مقدار ثابتی ندارند و از یک نصب به نصب دیگر فرق میکنند، پس مقدارشان را در کد ننویسید و همان لحظه بپرسید. ساخت، انتشار و ورود دستی افراد فقط از پنل انجام میشود.
کانال
کانال، راهی است که پیام از آن میرود. رشتههایی که وجود دارند: push (پوش موبایل)، webpush (پوش مرورگر)، sms، email، inapp (صندوق داخل اپ)، messenger، و سه پیامرسان bale، eitaa و rubika.
سه پیامرسان را مستقیم روی کمپین نمینویسید: هرکدام را بنویسید به messenger ارتقا داده میشود و موقع ارسال، برای هر گیرنده جداگانه حل میشود. در دسترس بودن هر کانال فقط از روی تنظیمات حساب میشود، بدون اینکه چیزی امتحان شود: برای نمونه email وقتی در دسترس است که هم میزبان SMTP و هم نشانی فرستنده تنظیم شده باشند. کانال در دسترس نبودن، با دلیلش نشان داده میشود نه با پنهان شدن.
یک حفره را صریح میگوییم: webhook بهعنوان کانال روی کمپین پذیرفته میشود ولی هیچ فرستندهای برایش ساخته نشده. کمپینی که روی webhook نوشته شود برای کل مخاطب شکست میخورد. اگر میخواهید سناریو به سرویس خودتان درخواست بزند، آن یک نوع «کنش» در سناریو است، نه این کانال.
کلید نوشتن در برابر کلید API
دو نوع کلید وجود دارد و هیچکدام جای دیگری کار نمیکند.
| کلید نوشتن | کلید API | |
|---|---|---|
| پیشوند | wk_seg_ | sk_seg_ |
| میزبان | https://in.segmentic.net | https://api.segmentic.net |
| کجا مینشیند | داخل کد عمومی سایت یا اپ | فقط سمت سرور |
| چه میتواند بکند | نوشتن رویداد، ثبت دستگاه، اشتراک پوش، گرفتن پیامهای درونبرنامهای | هر چیزی که نقش و مجوزهایش اجازه بدهد |
| چه نمیتواند بکند | خواندن پرونده، ساخت کلید دیگر | استفاده روی میزبان ورود داده |
| کجا ساخته میشود | «SDK و اتصال» | «تنظیمات» و بعد «کلیدهای API» |
هر دو فقط یک بار کامل نمایش داده میشوند و از آن به بعد فقط هششان ذخیره است. دو پیشوند جدا هستند تا اسکنرهای اسرار کلید لو رفته را بشناسند و تا تشخیص شدت نشت در یک نگاه ممکن باشد.
اگر کلید نوشتن را روی API مدیریتی بفرستید، پاسخ ۴۰۱ است با کد اختصاصی write_key_rejected و پیامی که میگوید این کلید SDK است و اینجا کلید مدیریتی لازم است. این خطا کد جدا دارد چون اشتباه رایج است و پاسخ عمومی، آدم را دنبال مشکل اشتباه میفرستد. برعکسش کد جدا ندارد.
مجوزها روی کلید API از نقشش میآیند. کلیدی که نقش owner داشته باشد ساخته نمیشود، پس هیچ کلیدی نمیتواند حساب را منتقل یا حذف کند. ستون محدودکردن مجوزهای یک کلید در پایگاه داده هست ولی هیچ کدی در آن نمینویسد؛ یعنی هر کلیدی که محصول امروز میسازد کل نقشش را دارد و scoped در پاسخ GET /v1/whoami همیشه false است.
آخرین تفاوت، سقف مصرف است. API مدیریتی برای هر کلید در هر دقیقهٔ تقویمی یک بودجهٔ وزنی دارد که پیشفرضش ۶۰۰ واحد است: یک whoami یک واحد و یک گزارش ماندگاری بیستوپنج واحد. میزبان ورود داده هیچ محدودیت نرخی ندارد.