پرش به مستندات
Ruby

ردیابی بازشدن و کلیک

`emails.get_tracking` و کل فضای نام `tracking`.

یک پیام

tracking.rb
report = client.emails.get_tracking("msg_3f9a1c07d2b84e6a9c5b1f20") puts "#{report[:openCount]} opens from #{report[:recipients].size} recipients"report[:links].each { |link| puts "#{link[:url]} #{link[:clickCount]}" }

پیامی که هرگز ردیابی نشده، به‌جای گزارشی خالی، یک OpenEmail::NotFoundError را raise می‌کند که not_found? آن true است. «چیزی ثبت نکردیم» و «کسی بازش نکرد» دو پاسخ متفاوت‌اند و نباید پاسخی مشترک داشته باشند. پیامی که با کلید test فرستاده شود هرگز ردیابی نمی‌شود، پس همیشه همین خطا را raise می‌کند.

در سراسر صندوق

tracking_report.rb
client.tracking.list(opened: false, days: 7, limit: 100)client.tracking.get_stats(days: 30, offset_minutes: Time.now.utc_offset / 60)client.tracking.get("msg_3f9a1c07d2b84e6a9c5b1f20")client.tracking.list_opens("msg_3f9a1c07d2b84e6a9c5b1f20", include_machine: true)client.tracking.list_clicks("msg_3f9a1c07d2b84e6a9c5b1f20")

list، list_opens و list_clicks یک OpenEmail::Page برمی‌گردانند، و list_all، iterate، list_all_opens، iterate_opens، list_all_clicks و iterate_clicks همهٔ صفحه‌ها را برایتان می‌پیمایند. get، list_opens و list_clicks هم شناسهٔ ارسال msg_… را می‌گیرند و هم شناسهٔ خودِ رکورد ردیابی، tmsg_….

فضای نامی از آنِ خودش است نه چند متد روی emails، و دلیلش پوشش است: emails رکوردهای ارسال را فهرست می‌کند، که فقط برای نامه‌ای وجود دارند که همین API رسیدگی کرده باشد. کامپوزر، ابزارهای MCP و دستیار همه بدون آن می‌فرستند، پس گزارشی که روی emails ساخته شود گزارشی دربارهٔ ترافیک API شما می‌شد، نه دربارهٔ صندوق پستی.

خواندن صادقانهٔ اعداد

جفتمعنایش چیست
opens و clicksآنچه اعمال شد: اینکه پیام با pixel یا با پیوندهای بازنویسی‌شده بیرون رفت یا نه.
opened و clickedآنچه رخ داد.
openCountبازدیدهای شمرده‌شده. اسکنرها و پروکسی‌های حریم خصوصی کنار گذاشته شده‌اند.
openCountRawهمهٔ بازدیدها. نقل‌کردن این عدد به‌عنوان تعامل، همان راهی است که نرخ باز شدن از 100% بالاتر می‌رود.
attributableاینکه آیا یک خوانده‌شدن اصلاً می‌تواند به گیرنده‌ای نام‌برده نسبت داده شود یا نه.

نرخ‌های tracking.get_stats روی پیام‌های «ردیابی‌شده» محاسبه می‌شوند، هرگز روی همهٔ آنچه فرستاده شده. وگرنه صندوقی که از هر ده پیام یکی را ردیابی می‌کند چنان به نظر می‌رسید که انگار فروپاشیده است. openRate و clickRate درصدهایی‌اند که تا یک رقم اعشار گرد شده‌اند، مانند 42.5، نه کسرهایی میان 0 و 1.

پارامترها: tracking.list

openedBoolean
`true` پیام‌هایی را انتخاب می‌کند که دست‌کم یک open شمرده‌شده دارند، `false` پیام‌های ردیابی‌شده‌ای را که هیچ‌کدام را ندارند. هیچ‌کدام پیش‌فرض نیست، و `false` هرگز به معنای نامهٔ ردیابی‌نشده نیست، که اصلاً در این فهرست نمی‌آید.
clickedBoolean
همان فیلتر برای کلیک‌های شمرده‌شده، که مستقل از `opened` اعمال می‌شود. هر دو را می‌شود داد، و آنگاه پیام‌ها باید هر دو را برآورده کنند.
daysInteger
چند روز از اکنون به عقب نگاه شود، 1 تا 365 با پیش‌فرض 30، و بیرون از این بازه یک 422 است. پنجره بر اساس زمان ساخته شدن رکورد ردیابی اندازه گرفته می‌شود، و فقط رکوردهایی فهرست می‌شوند که ارسالشان واقعاً انجام شده است.
minutesInteger
به‌جای آن، پنجره برحسب دقیقه، از 1 تا 527040، که وقتی هر دو تنظیم شوند بر `days` مقدم است. پنجرهٔ کوتاه‌تر از یک روز به `grain` ریزتری نیاز دارد.
grainString
`minute`، `hour` یا `day`، با پیش‌فرض `day`. فقط آغاز پنجره را به پایین گرد می‌کند، تا این فهرست با `get_stats` که با همان دانه‌بندی خوانده شود هم‌خوان باشد، و در شکل پاسخ هیچ اثری ندارد.
limitInteger
تعداد گزارش در هر صفحه، 1 تا 200 با پیش‌فرض 50، تازه‌ترین اول. `next_cursor` صفحه را با همان فیلترها به‌عنوان `cursor:` پس بدهید تا صفحهٔ بعد بیاید، یا بگذارید `list_all` و `iterate` کل پنجره را بپیمایند.
cursorString
`next_cursor` صفحهٔ قبل، یک شناسهٔ `tmsg_`.
api_keyString
به‌جای کلید کلاینت با این کلید فهرست می‌گیرد.

پاسخ: گزارش ردیابی

emails.get_tracking و tracking.get یک گزارش را به‌صورت یک Hash با کلیدهای Symbol برمی‌گردانند، و tracking.list صفحه‌ای از آن‌ها را برمی‌گرداند.

objectString
روی گزارشی که به‌خودی‌خود گرفته شود، از راه `tracking.get`، `tracking.list` یا `emails.get_tracking`، همیشه `tracking`. همان گزارش وقتی به شکل `tracking` درون پیامی از `emails.get` تو در تو بیاید، این کلید را ندارد، چون آنجا بخشی از همان پیام است نه چیزی که جداگانه گرفته شده باشد.
idString
شناسهٔ خودِ رکورد ردیابی، `tmsg_…`. `list_opens` و `list_clicks` بر اساس همین کلید کار می‌کنند، و `msg_…`ی که به آن‌ها داده شود نخست به‌عنوان همین جست‌وجو می‌شود.
sendIdString or nil
ارسال `msg_…` که این رکورد با آن متناظر است، و هر جا رکورد ارسالی نوشته نشده باشد nil. کامپوزر، `sendEmail` در MCP و دستیار، همگی بدون آن ارسال می‌کنند. ردیابی کل صندوق پستی را پوشش می‌دهد، نه فقط ترافیک API را.
threadIdString or nil
پس از ارسال پر می‌شود تا یک رابط خواندن بتواند دوباره پیام را پیدا کند، و هر جا درایور چیزی گزارش نکرده باشد nil است. حیاتی نیست: رکوردی که این فیلدش nil است هم شمرده می‌شود.
messageIdString or nil
همان Message-ID مطابق RFC 5322، نه شناسهٔ ما. این هم پس از ارسال پر می‌شود، و هر جا لایهٔ انتقال چیزی برای پر کردنش برنگردانده باشد nil است.
subjectString or nil
موضوع، همان‌گونه که هنگام ارسال بوده. روی پیامی که بدون موضوع ثبت شده nil است.
fromString
آدرس فرستنده، که روی خودِ رکورد کپی می‌شود نه اینکه از ارسال join شود. گزارش‌ها مدت‌ها بعد خوانده می‌شوند و آدرسی که از آن زمان اصلاح یا حذف شده باشد در غیر این صورت تاریخ را بازنویسی می‌کرد.
sourceString
کدام بخش آن را فرستاده: `composer`، `api`، `mcp`، `ai` یا `queue`. ممکن است بخشی ظاهر شود که این gem هنوز نامش را نمی‌برد، پس با مقدار ناشناخته به‌عنوان اطلاعات رفتار کنید نه خطا.
sentAtString or nil
زمانی که پیام رفته است، به‌صورت یک لحظهٔ ISO 8601. روی رکوردی که ارسالش هرگز کامل نشده nil است. `tracking.list` این‌ها را کنار می‌گذارد، `get` نه.
opensBoolean
اینکه آیا روی این پیام پیکسل اعمال شده است یا نه. این همان کاری است که انجام شده، نه آنچه تنظیم حساب اکنون می‌گوید.
clicksBoolean
اینکه آیا پیوندهای این پیام بازنویسی شدند یا نه. وقتی بدنه هیچ پیوندی نداشته false است، چون آنگاه چیزی تغییر نکرده و رکوردی که خلافش را ادعا کند با بایت‌ها جور درنمی‌آمد.
openedBoolean
اینکه آیا در میان نسخه‌ها هیچ open شمرده‌شده‌ای ثبت شده است یا نه. آن را در کنار `opens` بخوانید: نبودِ داده به‌دلیل جمع‌نشدنش، با نخواندنِ پیام از سوی هیچ‌کس، دو واقعیت متفاوت است.
clickedBoolean
اینکه آیا هیچ click شمرده‌شده‌ای ثبت شده است یا نه. شاهدی قوی‌تر از یک open است، چون تصویرها بسیار بیشتر از آنکه پیوندها دنبال‌نشده بمانند مسدود می‌شوند.
attributableBoolean
اینکه آیا هر خوانده‌شدنِ اینجا می‌تواند به گیرنده‌ای نام‌برده نسبت داده شود یا نه. همان لحظه که نسخه‌ای نسبت‌داده‌نشده فعالیت شمرده‌شده نشان دهد false می‌شود، که همان حالت چندگیرنده‌ای است که یک بدنه زیر یک توکن به کل فهرست می‌رود؛ پس پیش از نوشتن «باب این را باز نکرده است» آن را بررسی کنید.
openCountInteger
باز شدن‌هایی که گمان می‌رود کار یک آدم بوده‌اند، جمع‌زده روی نسخه‌ها. بازدیدهای ماشینی کنار گذاشته می‌شوند و تکرارها در سی ثانیه در یکی جمع می‌شوند، پس این همان عددی است که باید جلوی چشم خواننده گذاشت.
clickCountInteger
کلیک‌های شمرده‌شده، جمع‌زده روی نسخه‌ها. به ازای هر پیوند یکتاسازی می‌شود نه به ازای هر پیام، پس دو پیوند متفاوت که با چند ثانیه فاصله دنبال شوند دو کلیک‌اند.
openCountRawInteger
هر واکشی pixel، با احتساب اسکنرها و پراکسی‌های حریم خصوصی. `openCountRaw` منهای `openCount` نشان می‌دهد چند تا کنار گذاشته شده‌اند، واکشی‌های ماشینی و تکرارهای درون سی ثانیه روی هم، و تنها شاهد موجود بر این است که این پالایش اصلاً رخ داده.
clickCountRawInteger
هر بازدید از یک پیوند بازنویسی‌شده، با احتساب بازدیدهای ماشینی و تکرارها.
firstOpenAtString or nil
نخستین باز شدنِ شمرده‌شده در میان نسخه‌ها، و تا وقتی هیچ‌کدام نباشد nil. بازدیدهای ماشینی هرگز آن را جابه‌جا نمی‌کنند.
lastOpenAtString or nil
تازه‌ترین باز شدنِ شمرده‌شده در میان نسخه‌ها، و تا وقتی هیچ‌کدام نباشد nil.
firstClickAtString or nil
نخستین کلیکِ شمرده‌شده در میان نسخه‌ها، و تا وقتی هیچ‌کدام نباشد nil.
lastClickAtString or nil
تازه‌ترین کلیکِ شمرده‌شده در میان نسخه‌ها، و تا وقتی هیچ‌کدام نباشد nil.
recipientsArray<Hash>
برای هر نسخهٔ ردیابی‌شده یک ورودی: در جایی که لایهٔ انتقال اجازه می‌دهد بایت‌ها برای هر فرد متفاوت باشد، به ازای هر گیرنده، و جایی که چنین نیست، یک ورودی مشترکِ واحد. ورودی مشترک حذف می‌شود مگر آنکه واقعاً چیزی روی آن ثبت شده باشد، پس یک ردیف دست‌نخوردهٔ «کسی» هرگز کنار نام‌های واقعی نمی‌نشیند.
linksArray<Hash>
هر پیوندی که در این پیام بازنویسی شده است، به ترتیب جایی که در بدنه نشسته بود. جایی که پیوندی نبوده خالی است: پیامی که با `clicks` خاموش ارسال شده، یا پیامی که بدنه‌اش اصلاً پیوندی نداشته.

هر مدخل در recipients

emailString or nil
این نسخه به چه کسی رفته است، با حروف کوچک و همان‌گونه که هنگام ارسال بوده. دقیقاً وقتی nil است که `attributed` برابر false باشد.
kindString or nil
`to`، `cc` یا `bcc`: نشانی روی کدام سرآیند آمده بود، تا گزارش همان‌طور خوانده شود که خودِ پیام خوانده می‌شد. روی نسخهٔ مشترک nil است، چون به هیچ نشانی‌ای تعلق ندارد.
attributedBoolean
اینکه این ردیف فردی را نام می‌برد یا نه. پیش از `email` آن را بخوانید: مقدار false یعنی نسخهٔ مشترک، که به محض ثبت هر بازدیدی روی آن فهرست می‌شود، و نسبت دادن نامی به آن بازدید، حتی در پیامی با یک گیرندهٔ واحد، همان یک واقعیتی را از خود می‌سازد که این سازوکار نمی‌تواند تأمینش کند.
openCountInteger
باز شدن‌های شمرده‌شده تنها روی همین نسخه، با همان استثناهای مجموع پیام: بازدیدهای ماشینی کنار گذاشته می‌شوند و تکرارها در فاصلهٔ سی ثانیه در یکی ادغام می‌شوند.
clickCountInteger
کلیک‌های شمرده‌شده تنها روی همین نسخه، که به‌جای هر نسخه، به ازای هر پیوند یکتاسازی می‌شود.
firstOpenAtString or nil
نخستین باز شدنِ شمرده‌شده روی این نسخه، و تا وقتی هیچ‌کدام نباشد nil.
lastOpenAtString or nil
تازه‌ترین باز شدنِ شمرده‌شده روی این نسخه، و تا وقتی هیچ‌کدام نباشد nil.
firstClickAtString or nil
نخستین کلیکِ شمرده‌شده روی این نسخه، و تا وقتی هیچ‌کدام نباشد nil.
lastClickAtString or nil
تازه‌ترین کلیکِ شمرده‌شده روی این نسخه، و تا وقتی هیچ‌کدام نباشد nil.

هر مدخل در links

idString
شناسهٔ خودِ پیوند، `lnk_…`. همان مقداری است که `linkId` در یک ردیف کلیک نام می‌برد، پس یک بازدید از `list_clicks` را می‌توان به مدخل اینجا بازگرداند.
urlString
مقصد واقعی پیوند، همان‌گونه که پیش از بازنویسی در پیام بوده است. بازهدایت‌کننده شناسه را به همین مقدار برمی‌گرداند و بازدیدکننده را روانه می‌کند.
labelString or nil
متن لنگر همان‌گونه که در پیام آمده بود، یا هر جا پیوند متنی نداشته nil، مثل یک تصویر یا یک URL خام. برای این است که گزارش بتواند بگوید «پیوند صفحهٔ قیمت‌ها» به‌جای نقل یک URL با سه پارامتر ردیابی روی آن، و هرگز جانشین `url` نمی‌شود.
clickCountInteger
بازدیدهای شمرده‌شدهٔ این پیوند، جمع‌بسته روی همهٔ نسخه‌ها. همان پنجرهٔ سی‌ثانیه‌ای به‌ازای هر پیوند که برای `clickCount` روی پیام به کار می‌رود.
clickCountRawInteger
هر بازدید از این پیوند، شامل بازدیدهای ماشینی و تکرارها.