Blog. Recent thinking and work we've done.

May 5, 2024

Dynamically track query (UTM) parameters and pass them in forms

Many months ago, the team over at MobiLoud wanted a way to know which of their paid ads their demo call bookings came from.

By default, UTM parameters were being appended to the landing page URL that the ads took visitors to, but that information was soon lost the moment they navigated to a different page.

And that's intended, because it turns out Google Analytics 4 marks the presence of UTM parameters in a URL as the start of a new browsing session.

So instead of making UTMs persists across all subsequent URLs people visit, we decided to write some JavaScript that:

1. Let's us define which query parameters we care about. We've included all UTM parameters by default, but you can include any kind that you like.
2. Saves the specified parameters from the current URL to the visitor's local storage.
3. Creates a hidden field with the name and value of each query parameter in all forms with class .passTrackedParams.

Here's our code:

  $(() => {
    var trackedParams = ["utm_source", "utm_campaign", "utm_medium", "utm_term", "utm_content"];
    var queryParams = new URLSearchParams(;
    for (var p of queryParams)
      if (trackedParams.includes(p[0]))
        localStorage.setItem(p[0], p[1]);
    for (var p of trackedParams)
      if (Object.hasOwn(localStorage, p))
          .append(`<input type="hidden" id="${p}" name="${p}" value="${localStorage.getItem(p)}"/>`);

To make use of it, make sure to add it before the </body> tag in all of your pages, and add the class .passTrackedParams to each of the forms you want query parameters added to!

Now, no matter how long after someone books a MobiLoud demo after visiting their website from an ad, the team will always know which of their marketing efforts to attribute that call to. And they have one convenient place to interpret that data--their form submissions.

Found this post useful? Contact us and let's work together on your marketing website.

April 30, 2024

MobiLoud's new homepage

Myself and the MobiLoud team just launched a new homepage, and we’re pretty proud of it. Let’s go over what changed, and how we collaborated to get this shipped.

Design Highlights

Background colour

New homepage hero
Old homepage hero

One notable change we've made is our choice of background colour. It was previously a light green (#D1FAE5) from our primary colour scale, and now, its a dark grey (#181818) from our neutral colour scale.

This change was one I tried on a whim and happened to like. We think it helps position MobiLoud upmarket as a "luxury" or "premium" solution for converting a website into a mobile app, rather than what you'd feel if you had visited their site with bright pastel-like colours.

Dynamically change navigation menu colour

Since we're now replacing all instances of light green background colours with a dark grey, we also need to change the navigation menu's colours to match.

Here's some jQuery we implemented to dynamically add styling to the navbar based on whether it's intersecting a div with dark background.

$(document).ready(function() {
  const navSticky = $('#navSticky');
  let sections = [];

  function calculatePositions() {
    sections = $('.section.neutral-900-bg').map(function() {
      const top = $(this).offset().top;
      const bottom = top + $(this).outerHeight();
      return { top, bottom };

  function updateNavClasses(isIntersecting) {
    navSticky.toggleClass('dark', isIntersecting);
    $('.nav-link, .dropdown-toggle, .logo-svg').toggleClass('neutral-50', isIntersecting);

  function checkIntersection() {
    const navStickyBottom = navSticky.offset().top + navSticky.outerHeight();
    const intersecting = sections.some(section => 
      navStickyBottom >= && navStickyBottom <= section.bottom


  $(window).on('resize', () => {
  }).on('scroll', checkIntersection);

This approach works for the time being, but in hindsight, it admittedly can be made much more performant by using the Intersection Observer API. Make use of our code at your own discretion.

Case Study component

New case study component
Old case study component

We've decided to only display a single case study at a time, which gave us the opportunity to make each one individually more compelling.

The titles have been replaced by customer testimonials, and we now have the space to showcase more metrics than we did previously.

Card slider

The MobiLoud team was inspired by PostHog's "You'll hate PostHog if..." section, and had a similar idea for themselves that would use a previous set of custom icons they had on-hand. The above is what we ended up building.

Instead of building it as a conventional slider, I decided on a "drag to scroll" interaction instead. Props to Phuoc Nhuyen's blog post for the code that made it work.

Tool compatibility

A question the MobiLoud team often gets from leads are whether their website's third party integrations will also work in their native mobile app.

The answer is yes, and we built this section communicate that. Each third party tool you see in the screenshot also links to a dedicated post written on it, with the "View All" button taking them to


Every project has its own beginnings. In this case, Nihal, MobiLoud’s Growth Marketing Manager, pitched the idea to me in our Kanban board in Basecamp.

Attached within it was a link to a rewrite of the page’s copy in Notion. The content strategy was largely his responsibility, and its implementation was mine.

Since a webpage is fundamentally markup, writing out the content in a Word-like document before designing in Figma is surprisingly effective. After all, it makes most logical sense for you to know what you want to say before you package it nicely.

From there, I take it to Figma to draft layouts for the content, and then start development once the picture is clear in my head.

It's also true that the medium influences the message — content and design form a two-way relationship. Once we got to see the copy inside a real landing page, we often find ourselves shortening and generally re-editing the copy to be more digestible, and this case was no different.

And that's that - how we redesigned and built the new MobiLoud homepage. If you're looking for a similar redesign of a website or landing page, you're welcome to reach out to me directly, and we'll be in touch in less than 24 hours.

April 23, 2024

On designers coding

Whether designers should code or not seems to be a topic of heated debate. As a designer whose stood on the sidelines, I've thought about it, and came to the realization that I should learn to code. And that's what I've been doing over the past couple months. Here's why.

Wanting to make my ideas real

When it comes down to it, a designer's job is to *draw* an interface. I want to be able to turn that interface into a real thing that people can use and interact with, without having to rely on someone else.

In large companies, my impression is that there's this odd disconnect between designers and developers. Designers view developers as these stuck-up assholes who never implement their work correctly, and developers view designers as annoyances who always complain about the font weights being incorrect, or the spacing between elements looking "off". I want to do away with this dichotomy by building my own designs - not complaining about how somebody else didn't.

When dealing with computers more broadly, and the web specifically, knowing how to code is to understand how they work - and I want to be a curious person.

It was admittedly uncomfortable for me to come to this realization, probably because programming is something I've always seen as difficult, and I didn't want to feel inadequate for not being able to do it well. I'd imagine this is what many designers feel when confronted with the notion that they should code. They're comfortable and don't want to have to move.

But with some prodding from my older brother (a developer), and growing frustration with not being able to build what I wanted, my attitude towards programming changed from something to be intimidated by to something that's necessary - and even exciting.

Thinking back, picking up any new skill has never not been an arduous process. That's just a part of the game until you become fluent.

Later iterations take place in code

Before I was set on programming, working with Webflow gave me an understanding of HTML and CSS. Unlike many other "no-code" website builders, I'm grateful that Webflow doesn't abstract these concepts away.

Through building websites for myself, and then for others, I realized it's far more efficient to start building the thing when the design is 80% there. Past that point, you have a solid idea of what you need to build, and yet you're adding even more pixel-perfect detail to it in an environment that users won't be in to see them. What's the point?

Tools like Figma are useful because they provide an environment that makes exploring different layouts a faster process than having to build each of them. Use it to compare and contrast, but fundamentally, they're just drawings.

MobiLoud, a client of mine, has a fairly mature website now. I almost never touch Figma before building new sections in a landing page, because I don't need to anymore. We've got a strong base of components to rely upon.

The closer a design is to completion, the more it makes sense to work in the closest environment to reality. And that happens to be in code.

Programming makes you have better ideas

Oftentimes, when designing something in Figma, I tend to have little regard for its technical feasibility. Seeing as front-end development is obviously more complex than drawing, I like the idea of drawing without a care, and then challenging myself to build whatever it is afterwards.

Overall, doing so has made me quite a bit more proficient with HTML and CSS -- but that approach is not without downsides. If I'm completely free of the constraints that development brings, I incur costs in performance, time to implement, and complexity in maintenance.

Building your ideas gives you the ability to design around these constraints, which not only forces more creativity out of you, but results in a more usable and maintainable websites/products. After enough time, your intuition on what's worth building gets better, and your design decisions consider a wider range of problems you'd encounter.

That is all - the 3 reasons I'm learning to code, from a designer's perspective. It's worth mentioning that right now, I mostly work on CRFT Studio alone. If you work as a designer at a company where development is a separate role, I would still imagine learning a bit of code will make you easier to work with.

A large part of my reason for coding simply came down to me wanting to know more about what I was making.