React Twitter NoTrack

A React component library for embedding Tweets without Twitter's tracking script.

react-twitter-notrack does exactly what it says on the tin: allow you to embed Tweets as React components without exposing your users to tracking. You can install it from npm with npm i react-twitter-notrack.

Unfortunately, things seem to have stopped working, probably as a result of Twitter improving their bot detection or shutting down their API. There were enough tradeoffs inherent in this project that I don't intend to continue maintaining it. Thus, it is no longer usable.

import { Tweet } from "react-twitter-notrack"
function App() {
return (
<Tweet id="20" apiUrl="https://twitter-proxy.breq.workers.dev">
)
}

Link to this section Motivation

I wanted to be able to embed Tweets on my website, so I looked into React-based Twitter embed libraries. The two that I found, react-twitter-widgets and react-twitter-embed operated similarly: they both used the Twitter widgets.

Twitter has a system of widgets that can be embedded on a website. They work by using a JavaScript library to dynamically include iFrames onto the page. I'm not a huge fan of this approach, for a couple reasons:

  • The iFrames tend to load in after everything else on the page, leading to a huge layout jump.
  • Embedding iFrames uses more resources.
  • Users who use tracker-blockers, like Firefox Enhanced Tracking Protection, might not see the Tweet at all.
  • Allowing Twitter to execute JavaScript on my webpage exposes my users to tracking without their consent.

I decided to try making my own Twitter embed, built as a pure React component without any imperative DOM manipulation.

Link to this section Technical Description

I started building out this project using Storybook. I had wanted to try out Storybook for a while by now. I really enjoyed how quickly it allowed me to iterate.

Using an official Twitter widget as a model, I tried to emulate the design as best I could. I built out this mockup using styled-components, which was another first for me. I think that styled-components was a good fit for this project--it's a lot lighter-weight than Tailwind, and there was no need for me to stick to a broader design system like my website as a whole. That said, for more ambitious projects, I'll probably stick with Tailwind to keep things looking cohesive.

Then came the data fetching. I noticed that the official Twitter embed was sending a request to cdn.syndication.twimg.com:

...and getting back a response with info about the tweet:

So, just call this endpoint from the React component and we're good, right?

...nope. Twitter uses CORS to only allow platform.twitter.com to access this endpoint. For the official embed, this isn't an issue, since the iFrame is loaded from that origin. But for our pirate embed, we'll need to find another way.

I ended up building a proxy with Cloudflare Workers to spoof the Origin header to Twitter and send back a permissive Access-Control-Allow-Origin to the client. This is pretty much the same approach I used for GenReGen's Pastebin proxy.

With that out of the way, I just had to fetch the data from the proxy. I used trusty old useSWR to get the job done.

Link to this section Results

This library doesn't produce embeds with as much polish as the official Twitter ones -- they don't show the original tweet when embedding a reply or quote tweet, and they don't show more than one image at a time for now. But overall, I think this resulted in something usable and more performant than the official embed. For a while, I used it for all the Twitter embeds on this website, and it checked all the boxes. I don't know if anyone else ever found it useful, but I'm still happy that I shared my work on NPM.