How we built our Tweets app

September 21st, 2020

We recently launched Apps, and with it, our first app “Tweets”. It lists all the tweets about your websites, and lets you jump right into the conversation. In this blog post, we’ll explain how we built it, and by doing so, ate our own dog food!

Too long, or in a hurry? Check out the full example on CodePen! Oh, and if you just want to retrieve the tweets, the endpoint can be accessed directly from our APIs.

Symmetrics (@getsymmetrics)

The tweets look like this, and even display how many retweets and likes it has, as well as how many people have clicked the link within! 😁

236 visits



What you’ll need

Pro-tip: You can also use our client package on npm to connect to our APIs.

Getting started

Head over to the Symmetrics Keys page and create an Authentication Key. While there, also take note of your Symmetrics user ID. You’ll need both to interface our APIs. From Twitter, we’ll need the Bearer authentication token.

Kicking off our project, we’ll define these as variables first:

const symmetricsUserId = 'ac76c1a2-79ff-4a5f-88fe-9b543182acad';
const symmetricsAuthenticationKey = 'JfJ0V8jiNEevhI5TDECja5Lw0wYVh0B48e1u';
const twitterBearerToken = 'AAinwi384h94fin34f8hwiow78hwoiesM';

// these don’t work, replace them with your own keys!

Retrieving hostnames

Unfortunately, we’re unable to search Twitter for links directly. We’ll need to compile a list of hostnames to search for to avoid having to input them manually. JsonQl to the rescue!

const symmetricsApiUrl = '';
const hostnamesQuery = `
    unique urlHost
    where urlHost != localhost
    where urlHost ^!= localhost:
    limit 5

async function getHostnames() {
    const response = await fetch(`${symmetricsApiUrl}?user-id=${symmetricsUserId}&authentication-key=${symmetricsAuthenticationKey}&query=${encodeURIComponent(hostnamesQuery)}`).then((response) => response.json());

    if (response.success === true) {
        return response.results;

    const error = new Error(response.error.message);
    error.code = response.error.code;
    throw error;

Our JsonQl query also removes any localhost hostnames from the list.

Searching Twitter for your website

Using the Twitter recent search endpoint, looking up your hostnames, now that we know them, is pretty straight forward!

const twitterApiUrl = '';

async function searchTwitter(query) {
    const response = await fetch(`${twitterApiUrl}?query=${encodeURIComponent(query)}`, {
        headers: {authorization: `Bearer ${twitterBearerToken}`}
    }).then((response) => response.json());

    if ( {

    const error = new Error(response.error.message);
    error.code = response.error.code;
    throw error;

Refer to the Twitter API documentation for information on how to extract more data from each tweet.

Putting it all together

Now that we’ve got both functions ready, we’ll use both in a simple utility function that creates a Twitter search query from the hostnames.

async function getWebsiteTweets() {
    const hostnames = await getHostnames();
    const query ={urlHost}) => `"https://${urlHost}"`).join(' OR ');
    return searchTwitter(query);

To retrieve page views and unique visits from each tweet, we use JsonQl to isolate referrals from From there, we can iterate over the tweets and check if the URL is present in the text, and apply respective metrics to each. And that’s pretty much it!

const referralsQuery = `
    where event == page_view
    where referrerHost ==
    where referrerBase !=
    set twitterReferrals = {get results}

    unique referrerBase
    each {
        get twitterReferrals
        where referrerBase == {get each.referrerBase}
        set each.pageViews = {count}
        set each.uniqueVisitors = {count {unique visitorId}}

async function getReferrals() {
    const response = await fetch(`${symmetricsApiUrl}?user-id=${symmetricsUserId}&authentication-key=${symmetricsAuthenticationKey}&query=${encodeURIComponent(referralsQuery)}`).then((response) => response.json());

    if (response.success === true) {
        return response.results;

    const error = new Error(response.error.message);
    error.code = response.error.code;
    throw error;

You can try any of the queries in the query console, or copy them to your own dashboard. Also, check out the CodePen for the complete, functional example. Not a Symmetrics user yet? Sign up now for a free 7-day-trial!

We will continue writing educational blog posts much like this one. Let us know if you’ve got feedback or ideas for our next post. See you around! ✌️