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.
2. Create a Link modelAnchor
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:
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:
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.
If you save, and visit the Link model schema once more, you should see the reverse relation to visits:
4. Create some linksAnchor
At this point it's probably worth creating some example links you can use during the next steps.
You can also schedule links to be published at a later time with Scheduled Publishing.
5. Query for Links by shortUrlAnchor
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 }) {iddestinationUrl}}
Let's test this out with the GraphCMS API Playground. Make sure to pass the variable shortUrl
:
Success! Our query is returning the destinationalUrl
. We'll use this later.
6. Create new Visits with Links with a MutationAnchor
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
:
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:
7. Configure a new code projectAnchor
Inside of a new directory, initialize NPM, and add our 2 dependencies:
mkdir cmslycd cmslynpm init -ynpm install -E graphql-request graphql
Next create the file [shortUrl].js
inside of the folder api
:
mkdir apitouch 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:
The Permanent Auth Token should also have restricted access:
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 }) {iddestinationUrl}}`;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!
You should now have your very own branded short URL service deployed to your (sub)domain!
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):
Then when viewing a Link content entry in the CMS you can quickly visit it using the button on the right:
Try it yourselfAnchor
All of the code is available on GitHub, or you can deploy yourself using the button below!