# بازخورد کاربران > https://docs.errora.org/products/user-feedback بازخورد کاربر فاصلهٔ میان «چیزی خراب شد» و «کاربر واقعاً می‌خواست چه کار کند» را پر می‌کند. ارورا بازخورد را از **سه جا** می‌پذیرد و همه را در **یک صندوق ورودی** جمع می‌کند، وصل به همان خطایی که کاربر دیده است. | منبع | مقدار `source` ذخیره‌شده | چه کسی می‌فرستد | | --- | --- | --- | | ویجت بازخورد | `widget` / `new_feedback_envelope` | `feedbackIntegration()` در SDK مرورگر | | فرم گزارش خطا | `crash_report_embed_form` | `Sentry.showReportDialog({ eventId })` | | API گزارش کاربر | `user_report_envelope` | سرویس خودتان، یا آیتم پاکت قدیمی `user_report` | هرکدام که به کارتان می‌آید را بردارید. بیشتر تیم‌ها **ویجت** را همه‌جا می‌گذارند و **فرم گزارش خطا** را در صفحهٔ خطای خودشان. ## گزینهٔ ۱ — ویجت بازخورد ویجت یک دکمهٔ شناور است که فرمی باز می‌کند. بخشی از SDK رسمی مرورگر Sentry است، پس چیز اضافه‌ای برای نصب وجود ندارد. ### راه‌اندازی ```javascript import * as Sentry from "@sentry/browser"; Sentry.init({ dsn: "https://@/", 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: "ممنون از شما!", }), ], }); ``` کل راه‌اندازی همین است. بازخوردها ظرف یکی دو ثانیه در صفحهٔ **بازخورد** پنل می‌نشینند. ### وصل‌کردن به دکمهٔ خودتان تزریق خودکار را خاموش کنید و فرم را خودتان باز کنید: ```javascript const feedback = Sentry.feedbackIntegration({ autoInject: false }); document.querySelector("#feedback-button").addEventListener("click", async () => { const form = await feedback.createForm(); form.appendToDom(); form.open(); }); ``` یا ویجت را به عنصری که دارید بچسبانید: ```javascript const unsubscribe = feedback.attachTo(document.querySelector("#feedback-button"), { formTitle: "گزارش مشکل", }); ``` ### ارسال بازخورد بدون هیچ رابط کاربری اگر فرم خودتان را دارید، محتوایش را مستقیم از طریق SDK بفرستید: ```javascript 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` | پیوند به [بازپخش نشست](/products/session-replay)، وقتی بازپخش روشن باشد | | `environment`، `release`، `platform` | از اسکوپ SDK | | `user_id`، `user_ip`، `user_agent` | فقط وقتی SDK بفرستد | | `source`، `status`، `created_at` | توسط ارورا تنظیم می‌شود | بازخوردی که `associated_event_id` دارد **به Issue همان رویداد می‌چسبد**، پس در صفحهٔ خطا می‌بینید کاربر دربارهٔ همان خطای دقیق چه گفته است. ## گزینهٔ ۲ — فرم گزارش خطا فرم گزارش خطا همان دیالوگ کلاسیک «انگار مشکلی پیش آمده» است که *بعد از* گرفتن خطا نشان می‌دهید. ```javascript Sentry.init({ dsn: "https://@/", beforeSend(event, hint) { // فقط برای خرابی‌های واقعی و قابل مشاهدهٔ کاربر فرم را نشان بدهید. if (event.exception && event.event_id) { Sentry.showReportDialog({ eventId: event.event_id }); } return event; }, }); ``` یا صریحاً، هرجا که خرابی را مدیریت می‌کنید: ```javascript const eventId = Sentry.captureException(err); Sentry.showReportDialog({ eventId, title: "مشکلی پیش آمد", subtitle: "تیم ما مطلع شد.", subtitle2: "اگر مایلید کمک کنید، بنویسید چه اتفاقی افتاد.", labelName: "نام", labelEmail: "ایمیل", labelComments: "چه اتفاقی افتاد؟", labelSubmit: "ارسال گزارش", labelClose: "بستن", user: { name: "نیما", email: "nima@example.com" }, }); ``` ### چطور کار می‌کند SDK یک تگ ` ``` ## گزینهٔ ۳ — API گزارش سمت سرور وقتی **سرویس شما** خطا را گرفته و توضیح کاربر را هم خودتان جمع می‌کنید (فرم پشتیبانی، ربات تلگرام، تماس تلفنی)، آن را به نقطهٔ بازخورد پروژه بفرستید: ```bash 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 یا یک [توکن دسترسی شخصی](/account/tokens)). - `event_id` هر دو شکل ۳۲ رقمی هگز و UUID خط‌دار را می‌پذیرد. - `comments` اجباری است (حداکثر ۴۰۹۶ نویسه)؛ بازخورد خالی با `400` رد می‌شود. SDKهای قدیمی که آیتم پاکت `user_report` می‌فرستند هم بدون کار اضافه در همین‌جا می‌نشینند. ## کار با صندوق ورودی صفحهٔ **بازخورد** همان صندوق ورودی است. هر ردیف پیام، فرستنده (یا *ناشناس*)، منبع، آدرس صفحه، خطای پیوسته و زمان را نشان می‌دهد. می‌توانید: - متن پیام را **جست‌وجو** کنید (`q`)، بر اساس **وضعیت**، **محیط** و *فقط بازخوردهای وصل به یک خطا* (`has_issue`) و بازهٔ زمانی فیلتر کنید. - **وضعیت را تغییر دهید** — از `unresolved` به `resolved`، یا علامت‌زدن به‌عنوان `spam`. - **خطای پیوسته را باز کنید** تا ردپای پشت شکایت کاربر را ببینید. - **بازپخش نشست را باز کنید**، وقتی بازخورد `replay_id` دارد. - یک بازخورد را **حذف** کنید. شمارنده‌های بالای صفحه (کل، رسیدگی‌نشده، وصل‌شده به خطا) خلاصهٔ وضعیت را می‌دهند. ### API ```text 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. **تنظیمات ← وب‌هوک‌ها** ← یک کانال بسازید (نگاه کنید به [هشدارها](/products/alerts)). 2. یک قاعدهٔ هشدار برای **بازخورد جدید کاربر** اضافه کنید و آن را به پروژه محدود کنید. یک قالب مفید برای کانال چت: ```text 📣 {{ 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` ویجت را روشن کنید |