DEV Community

loading...
Cover image for How we built an end-to-end encrypted feedback widget

How we built an end-to-end encrypted feedback widget

alexbh profile image Alex ・3 min read

We at Portabella recently released Portabella Feedback, it's a customisable, end-to-end encrypted feedback widget you can drop into your site in seconds. It's one of the first integrations built on top of Portabella via the @portabella/sdk, however it does live within Portabella itself, we decided not to spin it out as its own product (as we did with PrivaNote).

If you're wanting a closer look at exactly what Portabella Feedback is, we have a landing page at https://portabella.io/feedback where you can see what it looks like and a little marketing material about it.

This tutorial is going to provide more information around how it works and how we built it.

Overview

Portabella Feedback is a Preact widget distributed via our CDN. We allow injecting variables when you include the script into you page. As we mentioned above it leverages the @portabella/sdk to handle end-to-end encrypted data storage.

To include the widget on your site you'll need to include a code snippet that looks similar to this:

<script
  async
  defer
  src="https://widget.portabella.io/bundle.js"
  data-pf-token="<YOUR_TOKEN>"
  data-pf-project-id="<YOUR_PROJECT_ID>"
/>
Enter fullscreen mode Exit fullscreen mode

Creating a Preact Widget

Rendering a Preact application on a DOM node is very simple, we didn't use any fancy frameworks to enable this to happen. At it's core, to render a simple "Hello World" component it looks like the following

import { h, render } from "preact";

const element = document.getElementById("<ELEMENT_ID>");
render(<div>Hello World</div>, element);
Enter fullscreen mode Exit fullscreen mode

Everything else is just sugar on top of this concept.

Injecting styles

You can of course override the Widget styles manually by including CSS files, however for a no-code type approach we allow customising the widget in a nice GUI.

This process modifies the end script we ask users to include on their site. What we mean by modifying is adding data-pf-* tags to the resulting script so that we can grab those in our Preact component and update properties.

For example changingthe primary color of the widget looks like this from the script side

<script
  async
  defer
  src="https://widget.portabella.io/bundle.js"
  data-pf-token="<YOUR_TOKEN>"
  data-pf-project-id="<YOUR_PROJECT_ID>"
  data-pf-primary-color="blue"
/>
Enter fullscreen mode Exit fullscreen mode

and in our Preact component we can leverage inline styles to apply that new color:

const primaryColor = element.getAttribute(`data-pf-primary-color`);

return (
  <div style={{backgroundColor: primaryColor}}>...</div>
);
Enter fullscreen mode Exit fullscreen mode

Saving feedback

The final piece of the puzzle now that we have a configurable widget users can included on their page is actually saving feedback to Portabella.

That process is only a few lines of code and looks as follows:

async function submitFeedback ({ from, message, rating }) {
  const { Project } = await import("@portabella/sdk");
  const sdk = new Project(token, projectId);
  await sdk.fetchPublicKey();
  await sdk.addCard({
    title: "New Feedback submission",
    description: `
Rating: ${rating}

${from && `Submitted by: ${from}`}

${message}`
  });
}
Enter fullscreen mode Exit fullscreen mode

We do this trick of importing the @portabella/sdk on submission as it's a little heavy, and don't want to slow down users who don't interact with the widget. Doing it this way keeps the initial bundle to only a few kB downloaded.

After clicking submit (and a quick loading animation) your user feedback is on it's way to your Portabella project. End-to-end encryption has never been easier!

Discussion (0)

pic
Editor guide