Build your own branded short links with GraphQL & Serverless Functions

Learn how to use GraphCMS GraphQL Queries & Mutations to power a simple link shortener project in this tutorial.

Jamie Barton
Jamie Barton
GraphCMS URL Shortener

Marketing teams for years have been using short URLs to track click origins, and of course, to shorten those long winded slug based URLs.

You've most likely seen something like https://bit.ly/graphcms. The issue with these links is that the .ly extension is rather confusing for those not familiar with it, and it's "off brand".

Thankfully we can use Serverless Functions to deploy our own code to a custom (sub)domain that is closer to our brand. These custom Serverless functions can check if the link exists, track a "visit", redirect to the destination URL, and of course do absolutely anything else in between.

⚡️ We'll be using GraphCMS to model our GraphQL schema, and automatically provide a Query & Mutation API we can use.

📝 While GraphCMS has great content editing features, I want to focus this tutorial on the APIs powering that, and how you can use the API directly to add new content entries, and relate them to other models.

1. Create a new ProjectAnchor

Let's begin by creating a new GraphCMS project. You'll need to give it a name, pick a region where the data will be stored, and click Create to confirm.

Create a Project in GraphCMS

We'll begin by creating a Link model that will be used to send visitors to the required destination.

Once you've created the model, add the following fields:

Link model fields

3. Create a Visit modelAnchor

Now create the model Visit. This will be used to track every click to our Link we created earlier.

Once you've created the model, add a relation to the Link model we created earlier:

Link model relation

The relation will be a Many (Visit) to one (Link) relation. A Link has many Visits. You'll also want to make this a two way reference — we'll need this for a follow up guide on analytics later.

Create model reference

If you save, and visit the Link model schema once more, you should see the reverse relation to visits:

Link model fields with visits relation added

At this point it's probably worth creating some example links you can use during the next steps.

Save and Publish a new link

You can also schedule links to be published at a later time with Scheduled Publishing.

Scheduled Publishing Dialog

When we invoke a Serverless function, we'll want to pass the shortUrl from the URL the user is visiting, e.g. https://go.example.com/wtf and pass that onto a GraphQL query so we can fetch the destinationUrl if it exists.

GraphCMS automatically creates queries for the model + fields we defined above.

The query will look something like this:

query GetLinkByShortUrl($shortUrl: String!) {
link(where: { shortUrl: $shortUrl }) {
id
destinationUrl
}
}

Let's test this out with the GraphCMS API Playground. Make sure to pass the variable shortUrl:

GraphCMS API Playground

Success! Our query is returning the destinationalUrl. We'll use this later.

Every time someone invokes our Serverless function, and fetches a valid Link, we also want to track this link has been visited. We'll need to pass it the ID of the link we want to "connect".

GraphCMS automatically creates mutations for the model + fields we defined above.

The mutation will look something like this:

mutation CreateNewVisitForLink($linkId: ID!) {
createVisit(data: { link: { connect: { id: $linkId } } }) {
id
}
}

Let's again test this out inside the GraphCMS API Playground. Don't forget to pass the linkId:

API Playground Mutation

Success! The GraphQL mutation successfully connected the visit to the link. You can verify this by querying for all links, and their visits, or by viewing the entry within the Content Editor:

Saved Content Entry with new visits relation

7. Configure a new code projectAnchor

Inside of a new directory, initialize NPM, and add our 2 dependencies:

mkdir cmsly
cd cmsly
npm init -y
npm install -E graphql-request graphql

Next create the file [shortUrl].js inside of the folder api:

mkdir api
touch api/[shortUrl].js

Then inside of here instantiate a new GraphQLClient using graphql-request we installed earlier.

import { GraphQLClient, gql } from "graphql-request";
const graphcms = new GraphQLClient(process.env.GRAPHCMS_ENDPOINT, {
headers: {
Authorization: `Bearer ${process.env.GRAPHCMS_TOKEN}`,
},
});

In order for this to work, you'll need to obtain your GRAPHCMS_ENDPOINT, and create a new Permanent Auth Token (as GRAPHCMS_TOKEN ) and set this inside of the file .env:

GRAPHCMS_ENDPOINT=
GRAPHCMS_TOKEN=

You can configure this inside of your Project API Access settings:

Project API Access Settings

The Permanent Auth Token should also have restricted access:

Permanent Auth Token Permissions

8. Implement logic into Serverless functionAnchor

We'll now move use the gql import we defined above to encapsulate our GraphQL query and mutation we wrote earlier.

const GetLinkByShortUrlQuery = gql`
query GetLinkByShortUrl($shortUrl: String!) {
link(where: { shortUrl: $shortUrl }) {
id
destinationUrl
}
}
`;
const CreateNewVisitForLinkMutation = gql`
mutation CreateNewVisitForLink($linkId: ID!) {
createVisit(data: { link: { connect: { id: $linkId } } }) {
id
}
}
`;

We'll then check the shortUrl passed into the query from the page request, which we can use to kick off our query. The reason we used square brackets [] around the filename shortUrl this is because we'll be hosting our Serverless function with Vercel, and they treat this as a dynamic route.

export default async function handler(req, res) {
const { shortUrl } = req.query;
try {
const {
link: { id: linkId, destinationUrl },
} = await graphcms.request(GetLinkByShortUrlQuery, { shortUrl });
await graphcms.request(CreateNewVisitForLinkMutation, {
linkId,
});
res.status(301).redirect(destinationUrl);
} catch (err) {
console.log(err)
res.status(404).end("Not Found");
}
}

Finally create the file vercel.json in the root of your project and add the following:

{
"rewrites": [{ "source": "/:shortUrl*", "destination": "/api/:shortUrl*" }]
}

This will allow us to redirect all traffic from /:shortUrl to our Serverless function at /api/:shortUrl.

9. Deploy to VercelAnchor

We now need to deploy this to Vercel. Go ahead and create an account, login, and install the CLI.

Once you're logged into the CLI, you'll want to run vc --prod to deploy your code to production.

If you then open the Vercel project settings to configure the domain, you can add an existing domain or new one and set it as the production domain for your project!

Vercel Project Domain Settings

You should now have your very own branded short URL service deployed to your (sub)domain!

Finished product preview

Try visiting https://go.notrab.dev/gcms!

10. Add Preview URLsAnchor

If you've a lot of links you quickly want to visit, you can tell GraphCMS what the final URL will look like for each of your links.

Inside of the Settings for the Link model, add a preview URL similar to the below (giving it whatever "Name" you want):

Preview URL

Then when viewing a Link content entry in the CMS you can quickly visit it using the button on the right:

Preview URL button

Try it yourselfAnchor

All of the code is available on GitHub, or you can deploy yourself using the button below!

Deploy with Vercel


  • Jamie Barton
  • Developer Relations

    Jamie is a software engineer turned developer advocate. Born and bred in North East England, he loves learning and teaching others through video and written tutorials. Jamie maintains Build your DXP, Headless Commerce Resources, and GraphQL WTF.

Related articles

It's Easy To Get Started

GraphCMS plans are flexibly suited to accommodate your growth. Get started for free, or request a demo to discuss larger projects with more complex needs