Marten Bjork

I'm a Staff Creative Technologist at Shopify

Data Collection Widget

AlternativeTo is a software discovery site, helping you find alternatives to the apps you love and hate. I've been helping them develop a new version of their platform. Having good data is key to them, so they wanted to develop a “data collection widget” that lets their users answer questions about different apps (“Why do you like Figma?”).

Over ~12 days we planned and implemented this feature. The team consisted of me (design, React implementation), Ola (CTO, back-end) and Markus (CEO, product owner).


In previous design sprints, we learned that we must be very clear about what we're actually discussing. Otherwise it's easy to have one person thinking about typography, another about colors and a third one about the content. This is especially true when working remotely — you can't read body language or see what the other person is looking at.

So, this time we tried to be more deliberate in our design discussions. The first design aspect we discussed was where to place the widget. We wanted it to be visible, but not annoying. I drew up some examples so to guide the discussion.

Each position comes with it's own connotation: Upper left corner is “allow notifications?” land. A banner at the bottom screen screams “cookie banner”. A modal over the page is visible but annoying. After some debate, we decided to use the lower right corner on desktop and use a banner-style toggle on mobile.

Next, I sketched up the bare bones of the widget:

This is a quick step that saves a lot of time later. We caught a lot of minor design errors just by thinking everything through on a wireframe level.

After some iterations we had simplified the widget a lot:

Visual design

Next, we moved on to visual design. I quickly designed a few different versions of the modal:

Presenting multiple versions is very important when collaborating on design. It's what enables the discussions that move the project forward: “this design may not be too anonymous”, “this design feels too dull”… The real progress is made during these discussions — not when pushing pixels into perfection in Figma.

Next, I designed a bunch of different child views. This is a stress test — can our format handle all the UIs we may want to render down the road? Can different widgets live in the same container in a coherent way?

Finally, we had the entire flow figured out. We had simplified the overall UI. The child views felt future-proof and well designed.

Live documentation

Throughout our projects, we write a lot. We write for a few hours and then invite the rest of the team to comment. It's much more efficient and robust than asking questions on Slack all day. In this projects, we had various documents that we bounced back and forth, slowly improving the specification.


With the design and and specification in place, it was time to implement the widget in the new React (next.js) platform. The key points of the spec were:

  • It should be possible to render the data collection widget anywhere

  • It should be easy to render 1 or more child widgets — in any order

  • Child views should modular and live in isolation from the parent component (no leaky abstractions)

I created a top-level <DataCollector /> component that abstracts all the complexity away. This is all you need to kick off the data collection flow:

<DataCollector appId={123} widgets={['AskToLogin', 'FavoriteApp', 'FavoriteFeatures']} onClose={() => this.myCustomCallback()} />

It's easy to add new capabilities to the data collection system down the road. The child views can do whatever they want as long as they call props.done() at some point.

const MyCustomView = (props: ChildViewProps) => ( <button onClick={() => props.done()}>Go to next view</button> )

In reality, the child views are much more complicated — they include side effects and third party libraries. But to get started, you just new a few lines of code.

Finally, to enable a new child view, it needs to be registered in the componentMapping config:

/** * Define available widgets */ componentMapping: DataCollectionComponentMap = { MyCustomView: { component: MyCustomView, skippable: false, hideUI: true }, BestAlternative: { component: BestAlternative, skippable: true, hideUI: false }, Comment: { component: Comment, skippable: true, hideUI: false }, End: { component: End, skippable: false, hideUI: true, props: { done: () => this.hide() } } };


The feature is now in beta at AlternativeTo.

Created by Marten Bjork. Thanks for reading.