Feedback

The Bucket Browser SDK includes a UI you can use to collect feedback from user about particular features.

image

Global feedback configuration

The Bucket Browser SDK feedback UI is configured with reasonable defaults, positioning itself as a dialog in the lower right-hand corner of the viewport, displayed in English, and with a light-mode theme.

These settings can be overwritten when initializing the Bucket Browser SDK:

const bucket = new BucketClient({
  publishableKey: "bucket-publishable-key",
  user: { id: "42" },
  feedback: {
    ui: {
      position: POSITION_CONFIG, // See positioning section
      translations: TRANSLATION_KEYS, // See internationalization section

      // Enable automated feedback surveys. Default: `true`
      enableAutoFeedback: boolean,

      /**
       * Do your own feedback prompt handling or override
       * default settings at runtime.
       */
      autoFeedbackHandler: (promptMessage, handlers) => {
        // See Automated Feedback Surveys section
      },
    },
  },
});

See also:

Automated feedback surveys

Automated feedback surveys are enabled by default.

When automated feedback surveys are enabled, the Bucket Browser SDK will open and maintain a connection to the Bucket service. When a user triggers an event tracked by a feature and is eligible to be prompted for feedback, the Bucket service will send a request to the SDK instance. By default, this request will open up the Bucket feedback UI in the user's browser, but you can intercept the request and override this behavior.

The live connection for automated feedback is established when theBucketClient is initialized.

Disabling automated feedback surveys

You can disable automated collection in the BucketClient constructor:

const bucket = new BucketClient({
  publishableKey: "bucket-publishable-key",
  user: { id: "42" },
  feedback: {
    enableAutoFeedback: false,
  },
});

Overriding prompt event defaults

If you are not satisfied with the default UI behavior when an automated prompt event arrives, you can can override the global defaults or intercept and override settings at runtime like this:

const bucket = new BucketClient({
  publishableKey: "bucket-publishable-key",
  user: { id: "42" },
  feedback: {
    autoFeedbackHandler: (promptMessage, handlers) => {
      // Pass your overrides here. Everything is optional
      handlers.openFeedbackForm({
        title: promptMessage.question,

        position: POSITION_CONFIG, // See positioning section
        translations: TRANSLATION_KEYS, // See internationalization section

        // Trigger side effects with the collected data,
        // for example posting it back into your own CRM
        onAfterSubmit: (feedback) => {
          storeFeedbackInCRM({
            score: feedback.score,
            comment: feedback.comment,
          });
        },
      });
    },
  },
});

See also:

Manual feedback collection

To open up the feedback collection UI, call bucketClient.requestFeedback(options) with the appropriate options. This approach is particularly beneficial if you wish to retain manual control over feedback collection from your users while leveraging the convenience of the Bucket feedback UI to reduce the amount of code you need to maintain.

Examples of this could be if you want the click of a give us feedback-button or the end of a specific user flow, to trigger a pop-up displaying the feedback user interface.

bucketClient.requestFeedback() options

Minimal usage with defaults:

bucketClient.requestFeedback({
  featureKey: "bucket-feature-key",
  title: "How satisfied are you with file uploads?",
});

All options:

bucketClient.requestFeedback({
  featureKey: "bucket-feature-key", // [Required]
  userId: "your-user-id",  // [Optional] if user persistence is
                           // enabled (default in browsers),
  companyId: "users-company-or-account-id", // [Optional]
  title: "How satisfied are you with file uploads?" // [Optional]

  position: POSITION_CONFIG, // [Optional] see the positioning section
  translations: TRANSLATION_KEYS // [Optional] see the internationalization section

  // [Optional] trigger side effects with the collected data,
  // for example sending the feedback to your own CRM
  onAfterSubmit: (feedback) => {
    storeFeedbackInCRM({
      score: feedback.score,
      comment: feedback.comment
    })
  }
})

See also:

Positioning and behavior

The feedback UI can be configured to be placed and behave in 3 different ways:

Positioning configuration

A modal overlay with a backdrop that blocks interaction with the underlying page. It can be dismissed with the keyboard shortcut <ESC> or the dedicated close button in the top right corner. It is always centered on the page, capturing focus, and making it the primary interface the user needs to interact with.

image

Using a modal is the strongest possible push for feedback. You are interrupting the user's normal flow, which can cause annoyance. A good use-case for the modal is when the user finishes a linear flow that they don't perform often, for example setting up a new account.

position: {
  type: "MODAL";
}

Dialog

A dialog that appears in a specified corner of the viewport, without limiting the user's interaction with the rest of the page. It can be dismissed with the dedicated close button, but will automatically disappear after a short time period if the user does not interact with it.

image

Using a dialog is a soft push for feedback. It lets the user continue their work with a minimal amount of intrusion. The user can opt-in to respond but is not required to. A good use case for this behavior is when a user uses a feature where the expected outcome is predictable, possibly because they have used it multiple times before. For example: Uploading a file, switching to a different view of a visualization, visiting a specific page, or manipulating some data.

The default feedback UI behavior is a dialog placed in the bottom right corner of the viewport.

position: {
  type: "DIALOG";
  placement: "top-left" | "top-right" | "bottom-left" | "bottom-right";
  offset?: {
    x?: string | number; // e.g. "-5rem", "10px" or 10 (pixels)
    y?: string | number;
  }
}

Popover

A popover that is anchored relative to a DOM-element (typically a button). It can be dismissed by clicking outside the popover or by pressing the dedicated close button.

image

You can use the popover mode to implement your own button to collect feedback manually.

type Position = {
  type: "POPOVER";
  anchor: DOMElement;
};

Popover feedback button example:

<button id="feedbackButton">Tell us what you think</button>
<script>
  const button = document.getElementById("feedbackButton");
  button.addEventListener("click", (e) => {
    bucketClient.requestFeedback({
      featureKey: "bucket-feature-key",
      userId: "your-user-id",
      title: "How do you like the popover?",
      position: {
        type: "POPOVER",
        anchor: e.currentTarget,
      },
    });
  });
</script>

Internationalization (i18n)

By default, the feedback UI is written in English. However, you can supply your own translations by passing an object in the options to either or both of thenew BucketClient(options) or bucketClient.requestFeedback(options) calls. These translations will replace the English ones used by the feedback interface. See examples below.

image

See default English localization keys for a reference of what translation keys can be supplied.

Static language configuration

If you know the language at page load, you can configure your translation keys while initializing the Bucket Browser SDK:

new BucketClient({
  publishableKey: "my-publishable-key",
  feedback: {
    ui: {
      translations: {
        DefaultQuestionLabel:
          "Dans quelle mesure êtes-vous satisfait de cette fonctionnalité ?",
        QuestionPlaceholder:
          "Comment pouvons-nous améliorer cette fonctionnalité ?",
        ScoreStatusDescription: "Choisissez une note et laissez un commentaire",
        ScoreStatusLoading: "Chargement...",
        ScoreStatusReceived: "La note a été reçue !",
        ScoreVeryDissatisfiedLabel: "Très insatisfait",
        ScoreDissatisfiedLabel: "Insatisfait",
        ScoreNeutralLabel: "Neutre",
        ScoreSatisfiedLabel: "Satisfait",
        ScoreVerySatisfiedLabel: "Très satisfait",
        SuccessMessage: "Merci d'avoir envoyé vos commentaires!",
        SendButton: "Envoyer",
      },
    },
  },
});

Runtime language configuration

If you only know the user's language after the page has loaded, you can provide translations to either the bucketClient.requestFeedback(options) call or the autoFeedbackHandler option before the feedback interface opens. See examples below.

bucketClient.requestFeedback({
  ... // Other options
  translations: {
    // your translation keys
  }
})

Translations

When you are collecting feedback through the Bucket automation, you can intercept the default prompt handling and override the defaults.

If you set the prompt question in the Bucket app to be one of your own translation keys, you can even get a translated version of the question you want to ask your customer in the feedback UI.

new BucketClient({
  publishableKey: "bucket-publishable-key",
  feedback: {
    autoFeedbackHandler: (message, handlers) => {
      const translatedQuestion =
        i18nLookup[message.question] ?? message.question;
      handlers.openFeedbackForm({
        title: translatedQuestion,
        translations: {
          // your static translation keys
        },
      });
    },
  },
});

Custom styling

You can adapt parts of the look of the Bucket feedback UI by applying CSS custom properties to your page in your CSS :root-scope.

For example, a dark mode theme might look like this:

image
:root {
  --bucket-feedback-dialog-background-color: #1e1f24;
  --bucket-feedback-dialog-color: rgba(255, 255, 255, 0.92);
  --bucket-feedback-dialog-secondary-color: rgba(255, 255, 255, 0.3);
  --bucket-feedback-dialog-border: rgba(255, 255, 255, 0.16);
  --bucket-feedback-dialog-primary-button-background-color: #655bfa;
  --bucket-feedback-dialog-primary-button-color: white;
  --bucket-feedback-dialog-input-border-color: rgba(255, 255, 255, 0.16);
  --bucket-feedback-dialog-input-focus-border-color: rgba(255, 255, 255, 0.3);
  --bucket-feedback-dialog-error-color: #f56565;

  --bucket-feedback-dialog-rating-1-color: #ed8936;
  --bucket-feedback-dialog-rating-1-background-color: #7b341e;
  --bucket-feedback-dialog-rating-2-color: #dd6b20;
  --bucket-feedback-dialog-rating-2-background-color: #652b19;
  --bucket-feedback-dialog-rating-3-color: #787c91;
  --bucket-feedback-dialog-rating-3-background-color: #3e404c;
  --bucket-feedback-dialog-rating-4-color: #38a169;
  --bucket-feedback-dialog-rating-4-background-color: #1c4532;
  --bucket-feedback-dialog-rating-5-color: #48bb78;
  --bucket-feedback-dialog-rating-5-background-color: #22543d;

  --bucket-feedback-dialog-submitted-check-background-color: #38a169;
  --bucket-feedback-dialog-submitted-check-color: #ffffff;
}

Other examples of custom styling can be found in our development example style-sheet.

Using your own UI to collect feedback

You may have very strict design guidelines for your app and maybe the Bucket feedback UI doesn't quite work for you. In this case, you can implement your own feedback collection mechanism, which follows your own design guidelines. This is the data type you need to collect:

type DataToCollect = {
  // Customer satisfaction score
  score?: 1 | 2 | 3 | 4 | 5;

  // The comment.
  comment?: string;
};

Either score or comment must be defined in order to pass validation in the Bucket API.

Manual feedback collection with custom UI

Examples of a HTML-form that collects the relevant data can be found in feedback.html and feedback.jsx.

Once you have collected the feedback data, pass it along to bucketClient.feedback():

bucketClient.feedback({
  featureKey: "bucket-feature-key",
  userId: "your-user-id",
  score: 5,
  comment: "Best thing I've ever tried!",
});

Intercepting automated feedback survey events

When using automated feedback surveys, the Bucket service will, when specified, send a feedback prompt message to your user's instance of the Bucket Browser SDK. This will result in the feedback UI being opened.

You can intercept this behavior and open your own custom feedback collection form:

new Bucketclient({
  publishableKey: "bucket-publishable-key",
  feedback: {
    autoFeedbackHandler: async (promptMessage, handlers) => {
      // This opens your custom UI
      customFeedbackCollection({
        // The question configured in the Bucket UI for the feature
        question: promptMessage.question,
        // When the user successfully submits feedback data.
        // Use this instead of `bucketClient.feedback()`, otherwise
        // the feedback prompt handler will keep being called
        // with the same prompt message
        onFeedbackSubmitted: (feedback) => {
          handlers.reply(feedback);
        },
        // When the user closes the custom feedback form
        // without leaving any response.
        // It is important to feed this back, otherwise
        // the feedback prompt handler will keep being called
        // with the same prompt message
        onFeedbackDismissed: () => {
          handlers.reply(null);
        },
      });
    },
  },
});

Last updated

Was this helpful?