From d54127c1cfe410bd39a18da4042676545433e477 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Fri, 17 Nov 2023 19:21:06 -0500 Subject: [PATCH 01/36] feat(feedback): Add SDK docs for User Feedback [WIP] --- src/components/platformSidebar.tsx | 8 + .../feature-stage-beta-user-feedback.mdx | 5 + .../user-feedback/install/javascript.mdx | 25 ++ .../pre-requisites/javascript.mdx | 3 + .../user-feedback/setup/javascript.mdx | 15 + .../common/enriching-events/user-feedback.mdx | 183 ------------ .../common/user-feedback/configuration.mdx | 264 ++++++++++++++++++ src/platforms/common/user-feedback/index.mdx | 146 ++++++++++ .../user_feedback_widget.png | Bin 9 files changed, 466 insertions(+), 183 deletions(-) create mode 100644 src/includes/feature-stage-beta-user-feedback.mdx create mode 100644 src/platform-includes/user-feedback/install/javascript.mdx create mode 100644 src/platform-includes/user-feedback/pre-requisites/javascript.mdx create mode 100644 src/platform-includes/user-feedback/setup/javascript.mdx delete mode 100644 src/platforms/common/enriching-events/user-feedback.mdx create mode 100644 src/platforms/common/user-feedback/configuration.mdx create mode 100644 src/platforms/common/user-feedback/index.mdx rename src/platforms/common/{enriching-events => user-feedback}/user_feedback_widget.png (100%) diff --git a/src/components/platformSidebar.tsx b/src/components/platformSidebar.tsx index f2fe49af631d8..da3f172b688df 100644 --- a/src/components/platformSidebar.tsx +++ b/src/components/platformSidebar.tsx @@ -74,6 +74,7 @@ export function SidebarContent({platform, guide, data}: ChildProps) { `/${pathRoot}/profiling/`, `/${pathRoot}/guides/`, `/${pathRoot}/crons/`, + `/${pathRoot}/user-feedback/`, ]} /> + ); } diff --git a/src/includes/feature-stage-beta-user-feedback.mdx b/src/includes/feature-stage-beta-user-feedback.mdx new file mode 100644 index 0000000000000..19ec7eb5a0e9a --- /dev/null +++ b/src/includes/feature-stage-beta-user-feedback.mdx @@ -0,0 +1,5 @@ + + +We've released a new version of User Feedback that supports feedback without requiring an error event. It is currently in open beta and subject to change. + + diff --git a/src/platform-includes/user-feedback/install/javascript.mdx b/src/platform-includes/user-feedback/install/javascript.mdx new file mode 100644 index 0000000000000..70bbc01be6417 --- /dev/null +++ b/src/platform-includes/user-feedback/install/javascript.mdx @@ -0,0 +1,25 @@ +The User Feedback integration is **already included** in your browser or framework SDK NPM packages. If you're using CDN bundles instead of NPM packages, you need to load the User Feedback integration CDN bundle in addition to your browser bundle: + +```bash {tabTitle: npm} +npm install --save @sentry/browser +``` + +```bash {tabTitle: Yarn} +yarn add @sentry/browser +``` + +```html {tabTitle: CDN} + + + + + +``` diff --git a/src/platform-includes/user-feedback/pre-requisites/javascript.mdx b/src/platform-includes/user-feedback/pre-requisites/javascript.mdx new file mode 100644 index 0000000000000..bbdaab4f11357 --- /dev/null +++ b/src/platform-includes/user-feedback/pre-requisites/javascript.mdx @@ -0,0 +1,3 @@ +For the sentry-replay integration to work, you must have the [Sentry browser SDK package](https://www.npmjs.com/package/@sentry/browser), or an equivalent framework SDK (for example, [@sentry/react](https://www.npmjs.com/package/@sentry/react)) installed. The minimum version required for the SDK is `7.27.0`. If you're on an older version of the SDK, please check the [migration document](https://github.com/getsentry/sentry-javascript/blob/master/MIGRATION.md). + +Session Replay requires Node 12+, and browsers newer than IE11. diff --git a/src/platform-includes/user-feedback/setup/javascript.mdx b/src/platform-includes/user-feedback/setup/javascript.mdx new file mode 100644 index 0000000000000..55e5118044f69 --- /dev/null +++ b/src/platform-includes/user-feedback/setup/javascript.mdx @@ -0,0 +1,15 @@ +```javascript +// import Sentry from your framework SDK (e.g. @sentry/react) instead of @sentry/browser +import * as Sentry from "@sentry/browser"; + +Sentry.init({ + dsn: "___PUBLIC_DSN___", + + integrations: [ + new Sentry.Feedback({ + // Additional SDK configuration goes in here, for example: + colorScheme: "light", + }), + ], +}); +``` diff --git a/src/platforms/common/enriching-events/user-feedback.mdx b/src/platforms/common/enriching-events/user-feedback.mdx deleted file mode 100644 index 047a17307a025..0000000000000 --- a/src/platforms/common/enriching-events/user-feedback.mdx +++ /dev/null @@ -1,183 +0,0 @@ ---- -title: "User Feedback" -sidebar_order: 105 -redirect_from: - - /learn/user-feedback/ -description: "Learn more about collecting user feedback when an event occurs. Sentry pairs the feedback with the original event, giving you additional insight into issues." ---- - -When a user experiences an error, Sentry provides the ability to collect additional feedback. You can collect feedback according to the method supported by the SDK. - - - -While this feature isn't currently supported for Ruby or most of its frameworks, it is supported for [Rails](/platforms/ruby/guides/rails/enriching-events/user-feedback/). - - - - - -**The user feedback feature is not currently supported for this SDK.** - - - - - -## User Feedback API - -The user feedback API provides the ability to collect user information when an event occurs. You can use the same programming language you have in your app to send user feedback. In this case, the SDK creates the HTTP request so you don't have to deal with posting data via HTTP. - - - -Sentry pairs the feedback with the original event, giving you additional insight into issues. Sentry needs the `eventId` to be able to associate the user feedback to the corresponding event. For example, to get the `eventId`, you can use or the return value of the method capturing an event. - - - - - - - - - -## Use the .NET SDK - - - -User Feedback for **[ASP.NET](/platforms/dotnet/guides/aspnet/enriching-events/user-feedback/#integration)** or **[ASP.NET Core](/platforms/dotnet/guides/aspnetcore/enriching-events/user-feedback/#integration)** supply integrations specific to supporting those SDKs. - - - -You can create a form to collect the user input in your preferred framework, and use the SDK's API to send the information to Sentry. You can also use the widget, as described below. If you'd prefer an alternative to the widget or do not have a JavaScript frontend, you can use this API or a [Web API](/api/projects/submit-user-feedback/). - -```csharp {tabTitle:C#} -using Sentry; - -var eventId = SentrySdk.CaptureMessage("An event that will receive user feedback."); - -SentrySdk.CaptureUserFeedback(eventId, "user@example.com", "It broke.", "The User"); -``` - -```fsharp {tabTitle:F#} -open Sentry - -let eventId = SentrySdk.CaptureMessage("An event that will receive user feedback.") - -SentrySdk.CaptureUserFeedback(eventId, "user@example.com", "It broke.", "The User") -``` - - - - - -## Embeddable JavaScript Widget - -Our embeddable JavaScript widget is useful when you may typically render a plain error page (the classic `500.html`) on your website. - -To collect feedback, the widget requests and collects the user's name, email address, and a description of what occurred. When feedback is provided, Sentry pairs the feedback with the original event, giving you additional insights into issues. - -The screenshot below provides an example of the User Feedback widget, though yours may differ depending on your customization: - -![An example of a user feedback widget with text boxes for user name, email, and additional details about the break.](user_feedback_widget.png) - -### Integration - -The widget authenticates with your public DSN, then passes in the Event ID that was generated on your backend. - - - -## Customizing the Widget - -You can customize the widget to your organization's needs, especially for localization purposes. All options can be passed through the `showReportDialog` call. - -An override for Sentry’s automatic language detection (e.g. `lang=de`) - -| Param | Default | -| ---------------- | ------------------------------------------------------------------------------------------------- | -| `eventId` | Manually set the id of the event. | -| `dsn` | Manually set dsn to report to. | -| `user` | Manually set user data _[an object with keys listed below]_. | -| `user.email` | User's email address. | -| `user.name` | User's name. | -| `lang` | _[automatic]_ – **override for Sentry’s language code** | -| `title` | It looks like we’re having issues. | -| `subtitle` | Our team has been notified. | -| `subtitle2` | If you’d like to help, tell us what happened below. – **not visible on small screen resolutions** | -| `labelName` | Name | -| `labelEmail` | Email | -| `labelComments` | What happened? | -| `labelClose` | Close | -| `labelSubmit` | Submit | -| `errorGeneric` | An unknown error occurred while submitting your report. Please try again. | -| `errorFormEntry` | Some fields were invalid. Please correct the errors and try again. | -| `successMessage` | Your feedback has been sent. Thank you! | -| `onLoad` | n/a | -| `onClose` | n/a | - - - -The optional callback `onLoad` will be called when users see the widget. You can use this to run custom logic, for example to log an analytics event: - - - -The optional callback `onClose` will be called when users close the widget. You can use this to run custom logic, for example to reload the page: - - - - - -## User Feedback API - -If you'd prefer an alternative to the widget or do not have a JavaScript frontend, you can use the [User Feedback API](/api/projects/submit-user-feedback/). - - - - - -## Embeddable JavaScript Widget - -Our embeddable JavaScript widget is useful when you may typically render a plain error page (the classic `500.html`) on your website. - -To collect feedback, the widget requests and collects the user's name, email address, and a description of what occurred. When feedback is provided, Sentry pairs the feedback with the original event, giving you additional insights into issues. - -The screenshot below provides an example of the User Feedback widget, though yours may differ depending on your customization: - -![An example of a user feedback widget with text boxes for user name, email, and additional details about the break.](user_feedback_widget.png) - -### Integration - -The widget authenticates with your public DSN, then passes in the Event ID that was generated on your backend. - - - -## Customizing the Widget - -You can customize the widget to your organization's needs, especially for localization purposes. All options can be passed through the `showReportDialog` call. - -An override for Sentry’s automatic language detection (e.g. `lang=de`) - -| Param | Default | -| ---------------- | ------------------------------------------------------------------------------------------------- | -| `eventId` | Manually set the id of the event. | -| `dsn` | Manually set dsn to report to. | -| `user` | Manually set user data _[an object with keys listed below]_. | -| `user.email` | User's email address. | -| `user.name` | User's name. | -| `lang` | _[automatic]_ – **override for Sentry’s language code** | -| `title` | It looks like we’re having issues. | -| `subtitle` | Our team has been notified. | -| `subtitle2` | If you’d like to help, tell us what happened below. – **not visible on small screen resolutions** | -| `labelName` | Name | -| `labelEmail` | Email | -| `labelComments` | What happened? | -| `labelClose` | Close | -| `labelSubmit` | Submit | -| `errorGeneric` | An unknown error occurred while submitting your report. Please try again. | -| `errorFormEntry` | Some fields were invalid. Please correct the errors and try again. | -| `successMessage` | Your feedback has been sent. Thank you! | -| `onLoad` | n/a - **an optional callback that will be invoked when the widget opens** | -| `onClose` | n/a - **an optional callback that will be invoked when the widget closes** | - -## User Feedback API - -If you'd prefer an alternative to the widget or do not have a JavaScript frontend, you can use the [User Feedback API](/api/projects/submit-user-feedback/). - - diff --git a/src/platforms/common/user-feedback/configuration.mdx b/src/platforms/common/user-feedback/configuration.mdx new file mode 100644 index 0000000000000..b62f7bb4cde7d --- /dev/null +++ b/src/platforms/common/user-feedback/configuration.mdx @@ -0,0 +1,264 @@ +--- +title: Configuration +sidebar_order: 6100 +description: "Learn about the general User Feedback configuration fields." +--- + + + +## User Feedback Widget + +### General + +The following options can be configured as options to the integration, in `new Feedback({})`: + +| key | type | default | description | +| --------- | ------- | ------- | ----------- | +| `autoInject` | `boolean` | `true` | Injects the Feedback widget into the application when the integration is added. This is useful to turn off if you bring your own button, or only want to show the widget on certain views. | +| `showBranding` | `boolean` | `true` | Displays the Sentry logo inside of the dialog | +| `colorScheme` | `"system" \| "light" \| "dark"` | `"system"` | The color theme to use. `"system"` will follow your OS colorscheme. | + +### User and Form +| key | type | default | description | +| --------- | ------- | ------- | ----------- | +| `showName` | `boolean` | `true` | Displays the name field on the feedback form, however will still capture the name (if available) from Sentry SDK context. | +| `showEmail` | `boolean` | `true` | Displays the email field on the feedback form, however will still capture the email (if available) from Sentry SDK context. | +| `isAnonymous` | `boolean` | `false` | Hides both name and email fields and does not use Sentry SDK's user context. | +| `useSentryUser` | `Record` | `{ email: 'email', name: 'username'}` | Map of the `email` and `name` fields to the corresponding Sentry SDK user fields that were called with `Sentry.setUser`. | + +By default the Feedback integration will attempt to fill in the name/email fields if you have set a user context via [`Sentry.setUser`](https://docs.sentry.io/platforms/javascript/enriching-events/identify-user/). By default it expects the email and name fields to be `email` and `username`. Below is an example configuration with non-default user fields. + +```javascript +Sentry.setUser({ + email: 'foo@example.com', + fullName: 'Jane Doe', +}); + + +new Feedback({ + useSentryUser({ + email: 'email', + name: 'fullName', + }), +}) +``` + +### Text Customization +Most text that you see in the default Feedback widget can be customized. + +| key | default | description | +| --------- | ------- | ----------- | +| `buttonLabel` | `Report a Bug` | The label of the widget button. | +| `submitButtonLabel` | `Send Bug Report` | The label of the submit button used in the feedback form dialog. | +| `cancelButtonLabel` | `Cancel` | The label of the cancel button used in the feedback form dialog. | +| `formTitle` | `Report a Bug` | The title at the top of the feedback form dialog. | +| `nameLabel` | `Name` | The label of the name input field. | +| `namePlaceholder` | `Your Name` | The placeholder for the name input field. | +| `emailLabel` | `Email` | The label of the email input field. | +| `emailPlaceholder` | `your.email@example.org` | The placeholder for the email input field. | +| `messageLabel` | `Description` | The label for the feedback description input field. | +| `messagePlaceholder` | `What's the bug? What did you expect?` | The placeholder for the feedback description input field. | +| `successMessageText` | `Thank you for your report!` | The message to be displayed after a succesful feedback submission. | + + +Example of customization + +```javascript +new Feedback({ + buttonLabel: 'Feedback', + submitButtonLabel: 'Send Feedback', + formTitle: 'Send Feedback', +}); +``` + +### Theme Customization +Colors can be customized via the Feedback constructor or by defining CSS variables on the widget button. If you use the default widget button, it will have an `id="sentry-feedback`, meaning you can use the `#sentry-feedback` selector to define CSS variables to override. + +| key | css variable | light | dark | description | +| --- | --- | --- | --- | --- | +| `background` | `--background` | `#ffffff` | `#29232f` | Background color of the widget actor and dialog | +| `backgroundHover` | `--background-hover` | `#f6f6f7` | `#352f3b` | Background color of widget actor when in a hover state | +| `foreground` | `--foreground` | `#2b2233` | `#ebe6ef` | Foreground color, e.g. text color | +| `error` | `--error` | `#df3338` | `#f55459` | Color used for error related components (e.g. text color when there was an error submitting feedback) | +| `success` | `--success` | `#268d75` | `#2da98c` | Color used for success-related components (e.g. text color when feedback is submitted successfully) | +| `border` | `--border` | `1.5px solid rgba(41, 35, 47, 0.13)` | `1.5px solid rgba(235, 230, 239, 0.15)` | The border style used for the widget actor and dialog | +| `boxShadow` | `--box-shadow` | `0px 4px 24px 0px rgba(43, 34, 51, 0.12)` | `0px 4px 24px 0px rgba(43, 34, 51, 0.12)` | The box shadow style used for the widget actor and dialog | +| `submitBackground` | `--submit-background` | `rgba(88, 74, 192, 1)` | `rgba(88, 74, 192, 1)` | Background color for the submit button | +| `submitBackgroundHover` | `--submit-background-hover` | `rgba(108, 95, 199, 1)` | `rgba(108, 95, 199, 1)` | Background color when hovering over the submit button | +| `submitBorder` | `--submit-border` | `rgba(108, 95, 199, 1)` | `rgba(108, 95, 199, 1)` | Border style for the submit button | +| `submitOutlineFocus` | `--submit-outline-focus` | `rgba(108, 95, 199, 1)` | `rgba(108, 95, 199, 1)` | Outline color for the submit button, in the focused state | +| `submitForeground` | `--submit-foreground` | `#ffffff` | `#ffffff` | Foreground color for the submit button | +| `submitForegroundHover` | `--submit-foreground-hover` | `#ffffff` | `#ffffff` | Foreground color for the submit button when hovering | +| `cancelBackground` | `--cancel-background` | `transparent` | `transparent` | Background color for the cancel button | +| `cancelBackgroundHover` | `--cancel-background-hover` | `var(--background-hover)` | `var(--background-hover)` | Background color when hovering over the cancel button | +| `cancelBorder` | `--cancel-border` | `var(--border)` | `var(--border)` | Border style for the cancel button | +| `cancelOutlineFocus` | `--cancel-outline-focus` | `var(--input-outline-focus)` | `var(--input-outline-focus)` | Outline color for the cancel button, in the focused state | +| `cancelForeground` | `--cancel-foreground` | `var(--foreground)` | `var(--foreground)` | Foreground color for the cancel button | +| `cancelForegroundHover` | `--cancel-foreground-hover` | `var(--foreground)` | `var(--foreground)` | Foreground color for the cancel button when hovering | +| `inputBackground` | `--input-background` | `inherit` | `inherit` | Background color for form inputs | +| `inputForeground` | `--input-foreground` | `inherit` | `inherit` | Foreground color for form inputs | +| `inputBorder` | `--input-border` | `var(--border)` | `var(--border)` | Border styles for form inputs | +| `inputOutlineFocus` | `--input-outline-focus` | `rgba(108, 95, 199, 1)` | `rgba(108, 95, 199, 1)` | Outline color for form inputs when focused | + +Here is an example of customizing only the background color for the light theme using the Feedback constructor configuration. +```javascript +new Feedback({ + themeLight: { + background: "#cccccc", + }, +}) +``` + +Or the same example above but using the CSS variables method: + +```css +#sentry-feedback { + --background: #cccccc; +} +``` + +### Additional UI Customization +Similar to theme customization above, these are additional CSS variables that can be overridden. Note these are not supported in the constructor. + +| Variable | Default | Description | +| --- | --- | --- | +| `--bottom` | `1rem` | By default the widget has a position of fixed, and is in the bottom right corner. | +| `--right` | `1rem` | By default the widget has a position of fixed, and is in the bottom right corner. | +| `--top` | `auto` | By default the widget has a position of fixed, and is in the bottom right corner. | +| `--left` | `auto` | By default the widget has a position of fixed, and is in the bottom right corner. | +| `--z-index` | `100000` | The z-index of the widget | +| `--font-family` | `"'Helvetica Neue', Arial, sans-serif"` | Default font-family to use| +| `--font-size` | `14px` | Font size | + +### Event Callbacks +Sometimes it’s important to know when someone has started to interact with the feedback form, so you can add custom logging, or start/stop background timers on the page until the user is done. + +Pass these callbacks when you initialize the Feedback integration: + +```javascript +new Feedback({ + onActorClick: () => {}, + onDialogOpen: () => {}, + onDialogClose: () => {}, + onSubmitSuccess: () => {}, + onSubmitError: () => {}, +}); +``` + +### Bring Your Own Button + +You can skip the default widget button and use your own button. Call `feedback.attachTo()` to have the SDK attach a click listener to your own button. You can additionally supply the same customization options that the constructor accepts (e.g. for text labels and colors). + +```javascript +const feedback = new Feedback({ + // Disable injecting the default widget + autoInject: false, +}); + +feedback.attachTo(document.querySelector('#your-button'), { + formTitle: "Report a Bug!" +}); +``` + +Alternatively you can call `feedback.openDialog()`: + +```typescript +import {BrowserClient, getCurrentHub} from '@sentry/react'; +import {Feedback} from '@sentry-internal/feedback'; + +function MyFeedbackButton() { + const client = getCurrentHub().getClient(); + const feedback = client?.getIntegration(Feedback); + + // Don't render custom feedback button if Feedback integration not installed + if (!feedback) { + return null; + } + + return ( + + ) +} +``` + +### Bring Your Own Widget + +You can also bring your own widget and UI and simply pass a feedback object to the `sendFeedback()` function. The `sendFeedback` function accepts two parameters: +* a feedback object with a required `message` property, and additionally, optional `name` and `email` properties +* an options object + +```javascript +sendFeedback({ + name: 'Jane Doe', // optional + email: 'email@example.org', // optional + message: 'This is an example feedback', // required +}, { + includeReplay: true, // optional +}) +``` + +Here is a simple example + +```html +
+ + +