The wonderful folks at Hopelab approached us with the idea of leveraging data visualization to highlight the inclusive and collaborative nature of their development process for imi, a web-based resource aimed at helping LGBTQ+ youth. Data Culture had worked with them previously on the project, helping to set up event tracking data collection and reporting on the site. Our mission for the Studio project was to tell a story of imi that encourages others to partner with Hopelab (and their extensive network) to make their own work more impactful.
Although this post is going to focus on the usage visualization we created for this project, a whole lot more work went into designing and building the site, and I encourage you to check it out here.
The first consideration in this process was actually an element of our ideation phase, which is focused on discussions about what to include in the narrative and how to represent it (you can read more about our process here). In this case, we decided that we wanted to show the actual impact imi has had after its launch. We also wanted to highlight how it has served a variety of young people from regions with different views on LGBTQ rights and inclusivity. All these signs pointed towards a data visualization geared towards exploring site engagement.
Luckily, our previous work on this project meant that not only did we have access to event tracking and usage data, but we were familiar with it. That being said, we also knew the data’s limitations. The dashboard is housed in Google Analytics, which specifically puts limitations on the way the data can be sliced and downloaded. We also wanted to make sure that any data representations were providing insights different from what was already available in the dashboard. The end result was a data export that leverages the url path and the region grouping.
This enabled a visualization that could map views and engagement time to certain pages and filter by location. After exporting, the data needed cleaning and exploration, which happened in RStudio (check out the code here). We also ended up needing to map each path to the guide, section, and content types, though this happened after the design phase once we had flushed out exactly what we were going to show.
The inspiration for this design came from a similar flower based visualization used to represent the OECD Better Life Index. The initial idea was to use the same principles but different shapes to show the usage across the four different guides in imi: stress, queerness, stigma, and gender. This is where it was important to lean on the age-old tradition of iteration.
The initial design was drawn up before the design language of the site had been finalized, so it featured a star based representation. After the organic shape and rounded corner elements were introduced to the site, we had to revisit the shapes used in the graph. Trying to do this without the elements looking overtly flower-like (or too similar to our inspiration piece) was a humbling experience. Looking back on the assortment of over 15 versions of the petal element designed, it becomes very clear that iteration is about sticking with the process until you find something that truly works.
This process was also complicated by the introduction of a second level of content breakdown. Initially, the plan was to show the views for each guide via the stem or the height of the element and then have one petal for each section of the guide (each guide has 3 sections), where the size is dependent on the amount of time spent on the page. After some brainstorming sessions, we decided to also include which type of content the user was engaging with of the four content categories: learn, activity, community, or resource.
By including this level of detail, we can show how users might be drawn to certain categories, but then how the different types of content might engage users for longer. This addition meant that instead of having three petals per stem, each stem would have three sections with between 1 and 4 pieces depending on the diversity of the content in each section (I hope that the accompanying mockups can illustrate this better than my description). The final design did end up looking very flower-like, with 3 flowers on each stem to represent the 3 sections and with the number of petals corresponding to the number of different content types within each. This visual paired with the location filter allows the elements to shrink and grow with the usage and interactions for users across different US states.
The issue with designing a custom visualization is that there’s likely no blueprint for how to build it. While I personally like the problem solving aspect, the initial part of development can seem like an insurmountable challenge. It’s in those moments that I remind myself that working in D3 is just digital arts and crafts. Everything can be broken down into a shape, color, or position. Remembering that a basic bar graph is just a specifically arranged set of lines and rectangles helped me assess how to approach building interactive flowers. In essence, the stems would operate in the same way as a bar graph, and the petals would use the same height value to get their position. Once those basics were in place, I was able to make the minor adjustments to match the mockup.
I will admit that due to the mix of using svg transformations and traditional x and y positioning, there was a good bit of math involved with calculating all the positions. That being said, I do often work through the math and then end up making random tweaks afterwards so that it looks better on the page. In the case of the petals, I worked out a system for checking the number of petals in each section (remember there are three sections on each stem) and then set positioning guidelines for 2, 3, and 4 petaled sections. The guidelines controlled the rotation and the arrangement around a center point with defined spacing in the middle. From there, each section was treated as a group, and the entire group was then repositioned to its correct place relative to the stem.
There were two main complications with these calculations:
- When using the rotation transformation, the origin does not change.
So when I used the getBBox() function to understand the size and position of the group of petals, the x and y values weren’t at the top left corner like usual. Instead, they corresponded to the center point of the group. This was managed by using the height and width values to figure out how far the edges of the group were from the center.
- The scaling transformation. The scales themselves were relatively straightforward (define a D3 linear scale and apply the scaled time value to the svg scale), but the transition on the petals meant that when I checked the size of the group, the petals hadn’t finished their rescaling and might grow bigger than the calculated boundaries. The fix here was to apply a setTimeout() function to the group repositioning so it happens after the scales are fully applied. You can actually see this order of operations happen when you change the location.
After building the initial structure, we decided to add a hover over to provide some more context for each group. As mentioned before, the intention of this graph is to show how users from different areas are interacting with imi. By including the hover state, we aimed to allow the viewer to not just pinpoint that the imi users are interested in the Support, Explore, or Affirm section of a certain guide, but that, for instance, the Support section of the Gender guide is actually focused on understanding your own gender identity. Implementing the text part of the hover was relatively straightforward, though I did take the time to build a function that will turn a long string into a paragraph in svg.
Traditionally, an svg text element is one long line unless you manually insert tspans with all the line breaks. The function calculates approximately how many words you want on each line and then loops through the string to make all the appropriate tspan elements (with some adjustments for word length). The function is on line 414 of this code. The harder part of the hover state was the circle around the group. Again this was complicated by the svg transformations, specifically the size and positioning of the petals and groups. The key here was to identify the hypotenuse of the group bounding box (again using the getBBox() function) and also to offset the center of the circle so that the group was properly centered within the circle. If that sounds confusing, think of it this way: If all the petals are the same size, then the origin of the petal group (the gap where all of them meet) would be in the same place as the center of the circle, but if one petal is significantly larger than the others, the center is no longer the same and needs to be shifted to accommodate the imbalance.
I could go on and on about the development of this visualization. If you’re so inclined, you can dive into all the code here.
A couple other development tricks for final polishing:
- We used a revised version of this excellent D3 axis transition example to update the y-axis value and range with the location change. This provides the slightest visual clue that values have either shrunk or grown, and the viewer should reassess the range.
- We ran into an issue with svg lines not reacting to css transitions when the stems were growing and shrinking. The fix for this is to use a transformation, but ultimately we decided those wouldn’t work for our purposes. The work around we ended up using is replacing the lines with a zero-width rectangle — not exactly conventional but it gets the job done.
The Final Product