بازخورد کاربران
بازخورد کاربر فاصلهٔ میان «چیزی خراب شد» و «کاربر واقعاً میخواست چه کار کند» را پر میکند. ارورا بازخورد را از سه جا میپذیرد و همه را در یک صندوق ورودی جمع میکند، وصل به همان خطایی که کاربر دیده است.
| منبع | مقدار source ذخیرهشده | چه کسی میفرستد |
|---|---|---|
| ویجت بازخورد | widget / new_feedback_envelope | feedbackIntegration() در SDK مرورگر |
| فرم گزارش خطا | crash_report_embed_form | Sentry.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، ایمیل، پیامک یا وبهوک:
- تنظیمات ← وبهوکها ← یک کانال بسازید (نگاه کنید به هشدارها).
- یک قاعدهٔ هشدار برای بازخورد جدید کاربر اضافه کنید و آن را به پروژه محدود کنید.
یک قالب مفید برای کانال چت:
📣 {{ 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 ویجت را روشن کنید |