As we roll out Data Narratives to more people, our focus is shifting from product features to distribution optimization. One of our biggest hurdles for this was SEO. A couple of months ago, we could not rank on the front page of Google for the term data narratives, despite owning the domain.

When we told potential customers about Data Narratives, their first instinct would be to search for us on Google. But they would find nothing, making them think that we must not be legit. This would often fluster me.

So since September, we focused on improving our front-end performance to improve our SEO ranking. Super happy that it has actually worked! We now consistently rank #1, and have a Click Through Rate of 23%

We went from often not being on the front page of Google, to consistently ranking #1
We went from often not being on the front page of Google, to consistently ranking #1

Figuring out what was broken

I am a front-end noob, so we tried out to diagnose issues with our page with Google’s Pagespeed Insights. We realized that our front-end performance was absolutely broken.

  • Large PNG images required too much bandwidth and killing performance. We saved 7MB in bandwidth by converting them to webp instead
  • Not lazy loading images (using the img tag instead of Next’s native Image) was killing performance
  • Embedded Tweets were causing significant performance issues
  • Loading heavy iframes (like YouTube) on page load instead of waiting until they were actually necessary was affecting page load times
  • We had an absurd layout shift problem linked to styled-components
  • Dynamic elements were causing significant layout shifts
  • Fixing images

    Our lowest hanging fruit was converting png images to webp (using cwebp). This saved us between 500kb and 2MB per image, and reduced the total bytes transferred on our home page by 7MB. It was stupid of us to not do this earlier, but better late than never!

    Next, we replaced (almost) all of our img tags with Next’s built in Image tags. This helps a ton with performance, without adding any programming complexity for us.

    Shifting from embedded tweet testimonials to building our “pseudo tweet” components

    Social testimonials by real people are one of the best ways to build trust in your website, so we initially included a lot of embedded tweets (twitter iframes) on our site. Something like this was a great testimonial, for example. But this led to a lot of unnecessary javascript being loaded.

    So we built our own tweet-like components, with a link back to the original tweet if someone else wanted to engage with it or check its authenticity. Our components look something like this

    Loading video iframes only after users click the play button

    We had a similar issue with YouTube’s embed iframe. Loading the iframe on page load slowed the page down considerably. We replaced it with a static webp image with a play icon, and now only load the iframe if a user clicks the play button.

    Fixing layout shifts

    Previously, our components moved around far too much on the website on page load. This was a jarring experience for users, and also affected our PageSpeed performance score. We did two things to fix this

    1. We enabled styled components in our next.config.js. We were using styled-components in many of pages, and Next (by default) was not loading them on initial page load. Adding compiler: { styledComponents: true } to our config fixed this.

    2. We added “dummy” components to all dynamic components. We use dynamic components to ensure that “heavy” elements can be rendered on the client side instead of the server side.

    But doing this caused all other components on a page to move significantly after dynamic components had finished loading.

    This had an easy fix – adding dummy components that are only visible while the dynamic components are in a loading state (like below, in the loading attribute).

    const ResponsiveNavbar = dynamic(
      () => import("../components/UI/Commons/ResponsiveNavbar"), {
        ssr: true,
        loading: () => <div style={{height: 72, width: "100%", backgroundColor: "rgb(74, 102, 237)"}}></div>

    Remaining performance improvements

    We are extremely performant now (specially on Desktop), but still have work to do.

  • We need to reduce unused css. We use antd as our UI Components library, which recommends globally importing its css file (~70kb). We will remove unnecessary components from this file to bring down its size
  • We can optimize the JS needed for the “Sign In With Google” button on our website, which should lead to significant performance improvements on mobile
  • Those are for much later, though! We wanted to make sure that people could discover us on Google and we did. Will focus on adding more data integrations and features to our platform for the next two months, before we start working on these optimizations.

    Enjoyed this post or have follow up questions? Do drop a note to @rishdotblog on Twitter or send an email to rishabh[at]!

    ← More blogs