پرش به مطلب اصلی

بازخورد کاربران

بازخورد کاربر فاصلهٔ میان «چیزی خراب شد» و «کاربر واقعاً می‌خواست چه کار کند» را پر می‌کند. ارورا بازخورد را از سه جا می‌پذیرد و همه را در یک صندوق ورودی جمع می‌کند، وصل به همان خطایی که کاربر دیده است.

منبعمقدار source ذخیره‌شدهچه کسی می‌فرستد
ویجت بازخوردwidget / new_feedback_envelopefeedbackIntegration() در SDK مرورگر
فرم گزارش خطاcrash_report_embed_formSentry.showReportDialog({ eventId })
API گزارش کاربرuser_report_envelopeسرویس خودتان، یا آیتم پاکت قدیمی user_report

هرکدام که به کارتان می‌آید را بردارید. بیشتر تیم‌ها ویجت را همه‌جا می‌گذارند و فرم گزارش خطا را در صفحهٔ خطای خودشان.

گزینهٔ ۱ — ویجت بازخورد​

ویجت یک دکمهٔ شناور است که فرمی باز می‌کند. بخشی از SDK رسمی مرورگر Sentry است، پس چیز اضافه‌ای برای نصب وجود ندارد.

راه‌اندازی​

import * as Sentry from "@sentry/browser";

Sentry.init({
dsn: "https://<public_key>@<your-errora-host>/<project_id>",
environment: "production",
release: "web@1.4.2",
integrations: [
Sentry.feedbackIntegration({
colorScheme: "system", // "light" | "dark" | "system"
showBranding: false,
autoInject: true, // نمایش دکمهٔ شناور
showName: true,
showEmail: true,
isNameRequired: false,
isEmailRequired: false,
// متن فارسی — پیش‌فرض ویجت انگلیسی است.
triggerLabel: "ارسال بازخورد",
formTitle: "ارسال بازخورد",
messagePlaceholder: "چه اتفاقی افتاد؟",
submitButtonLabel: "ارسال",
successMessageText: "ممنون از شما!",
}),
],
});

کل راه‌اندازی همین است. بازخوردها ظرف یکی دو ثانیه در صفحهٔ بازخورد پنل می‌نشینند.

وصل‌کردن به دکمهٔ خودتان​

تزریق خودکار را خاموش کنید و فرم را خودتان باز کنید:

const feedback = Sentry.feedbackIntegration({ autoInject: false });

document.querySelector("#feedback-button").addEventListener("click", async () => {
const form = await feedback.createForm();
form.appendToDom();
form.open();
});

یا ویجت را به عنصری که دارید بچسبانید:

const unsubscribe = feedback.attachTo(document.querySelector("#feedback-button"), {
formTitle: "گزارش مشکل",
});

ارسال بازخورد بدون هیچ رابط کاربری​

اگر فرم خودتان را دارید، محتوایش را مستقیم از طریق SDK بفرستید:

Sentry.captureFeedback({
name: "نیما",
email: "nima@example.com",
message: "فایل PDF فاکتور در سافاری سفید است.",
associatedEventId: lastEventId, // اختیاری — بازخورد را به آن خطا وصل می‌کند
});

ارورا چه چیزی ذخیره می‌کند​

ویجت یک آیتم پاکت feedback می‌فرستد که محتوایش در contexts.feedback است. ارورا این‌ها را نگه می‌دارد:

فیلدتوضیح
messageمتن بازخورد (حداکثر ۴۰۹۶ نویسه)
name، contact_emailهرچه فرم گرفته باشد
urlصفحه‌ای که کاربر در آن بوده
associated_event_idخطایی که کاربر دیده؛ برای وصل‌کردن بازخورد به همان Issue
replay_idپیوند به بازپخش نشست، وقتی بازپخش روشن باشد
environment، release، platformاز اسکوپ SDK
user_id، user_ip، user_agentفقط وقتی SDK بفرستد
source، status، created_atتوسط ارورا تنظیم می‌شود

بازخوردی که associated_event_id دارد به Issue همان رویداد می‌چسبد، پس در صفحهٔ خطا می‌بینید کاربر دربارهٔ همان خطای دقیق چه گفته است.

گزینهٔ ۲ — فرم گزارش خطا​

فرم گزارش خطا همان دیالوگ کلاسیک «انگار مشکلی پیش آمده» است که بعد از گرفتن خطا نشان می‌دهید.

Sentry.init({
dsn: "https://<public_key>@<your-errora-host>/<project_id>",
beforeSend(event, hint) {
// فقط برای خرابی‌های واقعی و قابل مشاهدهٔ کاربر فرم را نشان بدهید.
if (event.exception && event.event_id) {
Sentry.showReportDialog({ eventId: event.event_id });
}
return event;
},
});

یا صریحاً، هرجا که خرابی را مدیریت می‌کنید:

const eventId = Sentry.captureException(err);
Sentry.showReportDialog({
eventId,
title: "مشکلی پیش آمد",
subtitle: "تیم ما مطلع شد.",
subtitle2: "اگر مایلید کمک کنید، بنویسید چه اتفاقی افتاد.",
labelName: "نام",
labelEmail: "ایمیل",
labelComments: "چه اتفاقی افتاد؟",
labelSubmit: "ارسال گزارش",
labelClose: "بستن",
user: { name: "نیما", email: "nima@example.com" },
});

چطور کار می‌کند​

SDK یک تگ <script> تزریق می‌کند که به نقطهٔ embed ارورا اشاره دارد:

GET https://<host>/api/embed/error-page/?dsn=<dsn>&eventId=<event_id> → جاوااسکریپت دیالوگ
POST https://<host>/api/embed/error-page/?dsn=<dsn>&eventId=<event_id> → ثبت گزارش
  • احراز هویت با کلید عمومی DSN انجام می‌شود، نه با نشست — چون دیالوگ روی صفحهٔ کاربران شما اجرا می‌شود. این یک نقطهٔ نوشتن عمومی و عامدانه است.
  • هر برچسب یک پارامتر کوئری است. هر کلیدی در متن دیالوگ (title، subtitle، subtitle2، labelName، labelEmail، labelComments، labelClose، labelSubmit، errorGeneric، errorFormEntry، successMessage) قابل بازنویسی است — و همین‌طور است که دیالوگ فارسی منتشر می‌کنید.
  • محدودیت نرخ: ۱۰ ارسال در دقیقه به ازای هر IP.
  • گزارش به شناسهٔ رویدادی که داده‌اید و در نتیجه به Issue آن وصل می‌شود.

صفحه‌های رندرشده در سرور​

برای نمایش دیالوگ لازم نیست SDK بارگذاری شده باشد — تگ اسکریپت را خودتان در صفحهٔ خطا رندر کنید:

<script
src="https://<host>/api/embed/error-page/?dsn=<dsn>&eventId=<event_id>&labelSubmit=%D8%A7%D8%B1%D8%B3%D8%A7%D9%84">
</script>

گزینهٔ ۳ — API گزارش سمت سرور​

وقتی سرویس شما خطا را گرفته و توضیح کاربر را هم خودتان جمع می‌کنید (فرم پشتیبانی، ربات تلگرام، تماس تلفنی)، آن را به نقطهٔ بازخورد پروژه بفرستید:

curl -X POST "$ERRORA/api/v1/projects/$PROJECT_ID/feedback" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event_id": "9a1f4c2e7b8d4a1fa0c3e5d6b7a8c9d0",
"name": "نیما",
"email": "nima@example.com",
"comments": "بعد از زدن دکمهٔ پرداخت، صفحه قفل شد."
}'
  • به توکن کاربری با توانمندی issue:write روی آن پروژه نیاز دارد (توکن دسترسی JWT یا یک توکن دسترسی شخصی).
  • event_id هر دو شکل ۳۲ رقمی هگز و UUID خط‌دار را می‌پذیرد.
  • comments اجباری است (حداکثر ۴۰۹۶ نویسه)؛ بازخورد خالی با 400 رد می‌شود.

SDKهای قدیمی که آیتم پاکت user_report می‌فرستند هم بدون کار اضافه در همین‌جا می‌نشینند.

کار با صندوق ورودی​

صفحهٔ بازخورد همان صندوق ورودی است. هر ردیف پیام، فرستنده (یا ناشناس)، منبع، آدرس صفحه، خطای پیوسته و زمان را نشان می‌دهد.

می‌توانید:

  • متن پیام را جست‌وجو کنید (q)، بر اساس وضعیت، محیط و فقط بازخوردهای وصل به یک خطا (has_issue) و بازهٔ زمانی فیلتر کنید.
  • وضعیت را تغییر دهید — از unresolved به resolved، یا علامت‌زدن به‌عنوان spam.
  • خطای پیوسته را باز کنید تا ردپای پشت شکایت کاربر را ببینید.
  • بازپخش نشست را باز کنید، وقتی بازخورد replay_id دارد.
  • یک بازخورد را حذف کنید.

شمارنده‌های بالای صفحه (کل، رسیدگی‌نشده، وصل‌شده به خطا) خلاصهٔ وضعیت را می‌دهند.

API​

GET /api/v1/projects/{project_id}/feedback?q=&status=&environment=&has_issue=&stats_period=24h&limit=25&offset=0
POST /api/v1/projects/{project_id}/feedback # همان API گزارش بالا
GET /api/v1/projects/{project_id}/feedback/summary
GET /api/v1/projects/{project_id}/feedback/{id}
PATCH /api/v1/projects/{project_id}/feedback/{id} # {"status": "resolved" | "unresolved" | "spam"}
DELETE /api/v1/projects/{project_id}/feedback/{id}
GET /api/v1/issues/{issue_id}/feedback # هرچه دربارهٔ یک خطا گفته شده

باخبر شدن از بازخورد تازه​

بازخورد رویداد feedback.received را فعال می‌کند، پس می‌توانید آن را به هر کانالی بفرستید — تلگرام، بله، Mattermost، ایمیل، پیامک یا وب‌هوک:

  1. تنظیمات ← وب‌هوک‌ها ← یک کانال بسازید (نگاه کنید به هشدارها).
  2. یک قاعدهٔ هشدار برای بازخورد جدید کاربر اضافه کنید و آن را به پروژه محدود کنید.

یک قالب مفید برای کانال چت:

📣 {{ title }}
{{ body }}
{{ url }}

عیب‌یابی​

نشانهعلت / راه‌حل
دکمهٔ ویجت اصلاً دیده نمی‌شودfeedbackIntegration() در integrations نیست، یا autoInject: false است بدون فراخوانی attachTo/createForm
ویجت ارسال می‌کند ولی چیزی نمی‌رسدDSN اشتباه است یا مسدودکنندهٔ تبلیغات درخواست را خورده — تب Network مرورگر را برای فراخوانی envelope ببینید و گزینهٔ tunnel را در نظر بگیرید
هنگام ارسال، دیالوگ «خطای ناشناخته» می‌دهداز محدودیت ۱۰ ارسال در دقیقه گذشته‌اید، یا eventId معتبر نیست
دیالوگ باز نمی‌شودshowReportDialog پیش از Sentry.init صدا زده شده، یا بدون eventId در صفحه‌ای که رویدادی ثبت نشده
بازخورد می‌رسد ولی به خطایی وصل نیستassociated_event_id/event_id فرستاده نشده، یا رویدادی که نام برده در نمونه‌برداری حذف شده
پاسخ 403 از API گزارشتوکن روی آن پروژه توانمندی issue:write ندارد
همه‌چیز ناشناس استSDK کاربری نمی‌فرستد؛ Sentry.setUser({...}) را تنظیم کنید یا showEmail/showName ویجت را روشن کنید