Improving User Onboarding: Screenshot Audit Tool

One topic that every founder inevitably spends a lot of time on when building out their product is user onboarding.

Aggressively tackling the user onboarding issue earlier on is incredibly important to improve adoption, and to overall see your MVP reach the levels of success you are hoping for as you continue to iterate on your product.

Beyond implementing intuitive UX in your application itself, a large part of the user onboarding work goes into developing effective documentation and support: articles, tutorials, and videos. Easily consumable bites of information that can quickly get your user from point A to point B, and to give them a sense of progression.

Generally when compiling a tutorial of sorts, you’re going to be taking several screenshots of your app to go along with the text explaining it.

You can probably see where you might run into a conundrum during this process as you’re developing your MVP:

  • Your MVP is a constantly evolving piece of software. The appearance is changing fairly quickly as you mold your product to your customer’s needs.
  • You’ve written out several tutorials, created video assets and captured a huge amount of screenshots to help explain and get your users onboarded: but due to the rapid changing pace of the MVP, you’re finding you need to constantly scan old assets and replace them with their newer version.

It’s no wonder that the SaaS world has spent so much time and money investing in and understanding UX improvements. Every penny spent on optimizing a product’s UX is a penny saved on extensive documentation needs.

Unfortunately, not every app is simple enough to be able to get by without a great supporting cast of tutorials and articles to help users along.

We ran into this problem ourselves at SheetDream. We’d create a detailed use case or tutorial demonstrating how to build out some sort of app: and a few SheetDream feature releases later, find that a lot of our existing screenshots are out of date and could confuse our customers. Confused customers = terrible customer onboarding, and bad customer onboarding leads to an overall bad user product experience.

How We Solved It

We generally had a few different problems:

  • Use cases and tutorials on our main site ( containing out of date screenshots that need to be updated
  • External content marketing articles (Medium, other platforms) containing out of date screenshots
  • Our documentation, hosted by GitBook, containing out of date screenshots

What we needed was to be able to track all of the assets (images, GIFs, videos) used in all of this content in one central place and be able to quickly scan through every asset and mark the ones that are out of date.

So instead of having to manually peruse all of these data sources and scroll scroll scroll, we wanted to be able to view every image asset on a single page and click a button indicating that screenshot needs to be updated.

And on the other side: a view where we can see which assets need to be updated, where we can go and snap new screenshots, and update the image itself.

We wound up solving this issue with the following tools and platforms:

  • Airtable. Obviously! We built out a bit of an asset map linking articles to image assets, and some flag fields for indicating an image is out of date.
  • Image Link Grabber (Chrome extension): this helped us with extracting the URLs for all of the images we host on GitBook for building out our page/asset map in Airtable. (
  • SheetDream API tasks: we leveraged a handful of advanced features to greatly increase productivity and mapping of assets to articles. runs on WordPress, so we automatically sync the list of pages and media assets (images, GIFs) to Airtable using API tasks.
  • SheetDream transforms: transforms is an advanced feature that lets you build your own completely custom API endpoints on SheetDream by applying a JSONata transform to one or more data sources. Think of it like being able to build a custom SQL query.

We used API tasks to synchronize newly uploaded images and new pages directly to Airtable, which greatly reduces the amount of work needed when doing the asset mapping. We linked all of our tables in Airtable, starting with the Pages table which contained overall details for each article and links to all the images each page uses:

And here is the Images table, showing each individual image’s relationship to its Page.

And here is where some of the magic occurs: we link our Images table to our WPMedia and GitBookMedia tables, where we store details about assets from those two different platforms (WordPress and GitBook).

Each image will either have its source file being hosted on GitBook or WordPress, and each entry in the Images table should have some sort of file from one of those platforms connected to it.

We created a transform on SheetDream to build out a special API endpoint where you can pass it the image’s Key (for example, job-board-1 in the above screenshot) and it will return to you a 301 redirect to the original platform. You can then use this transform’s URL in place of your actual image URL.

    "statusCode": 301,
    "headers": {
        "Location": Images[Key=%.imagekey].AttachedMedia ? $eval(Images[Key=%.imagekey].AttachedMedia)[0].url : 
            (Images[Key=%.imagekey].`GitBook URL` ? 
                $eval(Images[Key=%.imagekey].`GitBook URL`)[0] : $eval(Images[Key=%.imagekey].`WP URL`)[0])
    "body": ""

This JSONata query basically queries our Images table for the passed in imagekey, and will grab one of either of: the URL from GitBook (if it exists), the URL from WordPress (if it exists), or the URL of the image hosted on Airtable.

So now, we can represent images using a URL like this where we aren’t necessarily concerned as to where it is hosted:

This makes it easy for us to share images across all our platforms, and from the Airtable end makes it trivial to change an image to a new one: all you have to do is unlink the old image and link the new image.

What Is The Benefit Of This Approach?

Unfortunately in WordPress, when you need to “update” an existing asset: say, a screenshot that is out of date, there is no straightforward way to do this. You have a few options:

  1. Upload a new version of the screenshot, and then manually go in and update the HTML.
  2. In the WordPress Media section, you can extract the filename of the image you want to place, rename your file on disk to match: then delete the old one, and re-upload
  3. If you use Elementor, or any other drag-and-drop style tool, you would need to go back and modify the actual page.

All of these approaches are unfortunately very prone to error and require a lot of manual work.

This approach removes the need to have to manually make changes to the HTML or Elementor page to contain a new screenshot — and does not require any error prone file management.

Instead, we create these Images in Airtable which basically serve as tags (represented in the Airtable under the column “Key”):

[page]-[order of appearance on page]

And the file itself sits behind the tag, so to speak.

This allows us to seamlessly swap an image for a newer version. It also serves as a great index of content and gives us draw relationships and organize asset data.

Automating The Assets

On the SheetDream side, we leverage API tasks to continuously query our WordPress API to sync newly added images and pages to Airtable:

So the process for changing an image becomes:

  • Upload the new image to WordPress
  • After a few minutes, the new image entry appears in Airtable the next time the GET /media API call above runs
  • On the Images table, unlink the old image and link to the newly synced image

Only Half The Problem

That trivializes how we share the images across platforms and how we can quickly update images, but it doesn’t solve the other problem, the real big one: the ability to quickly scan our images for ones that are out of date and to be able to mark them as having been changed.

This is where we built out an extremely simple tool using SheetDream’s simple HTML Handlebars.js templating to query our API and display all of our images, and a button for marking a particular image as having been changed:

Clicking “Mark As Changed” performs a PATCH call to our API which flips the “Has Changed” flag in Airtable. We have a view in Airtable showing these records:

This gives us a simple list of images that we know we’re going to need to perform updates on.

The tool itself only took around 30 lines of code (Handlebars.js, HTML and a little JavaScript), under an hour to build and test, and SheetDream was able to generate most of it for us in the “Embedding & Code” tab.

The New Process vs The Old Process

With the new tool in place, the SheetDream transform API in place, and Airtable setup with a complete mapping of assets/pages, we then built out a new process for keeping up with the images:

  • Every week we perform a scan of our old images in the audit tool. If an image has changed due to a new app release, we click “Mark As Changed”
  • We consult the “Has Changed” view in Airtable. For each image we go and capture a new screenshot which is up to date, and we upload it to WordPress.
  • SheetDream synchronizes WordPress back to the WPMedia table in Airtable after a few minutes. We then link the Image record to the new item in WPMedia and unlink the old one.
  • After a few minutes, the SheetDream transform API gets updated and points to the new image. This new image automatically gets updated in our content, because we used a link to the transform API instead of a direct link to the image itself

It takes only a handful of clicks to identify an image that needs to be changed, upload a new image, and link to it in Airtable. It’s very quick, doesn’t require any extensive context switching, and isn’t too error prone.

Contrast that with the old process:

  • Manually sifting through content across our entire domain, external pages (e.g. hosted on Medium) and identifying pages which contain out of date images
  • For each page we see that needs to be updated:
    • Capture new screenshot(s)
    • Upload the new screenshot(s) to WordPress
    • Scan the live page a 2nd time looking for the particular image we’re replacing, right clicking and locating that image’s URL
    • Find the reference to that particular URL in the page’s HTML, and replacing it with a URL to our new image.

This process is slightly less tedious when using something like Elementor, much more painful if you manually manage the HTML. Either way, it involves having to make a change to the page itself instead of just the image, and this opens up the possibility for error and accidentally making a change (e.g. structural, formatting, HTML errors) that could negatively affects the rest of the page. This isn’t a very scalable approach, especially as the amount of assets and pages stack up overtime. It involves a lot of switching gears and doesn’t allow the user to hone in on one task at a time.

Wrapping Up

We saw a lot of time savings and reduced a lot of headaches building out this app. It’s been a lifesaver and really helped formalize the way that we deal with content and assets.

It’s got the potential to really scale out in the future as well: having the assets mapped in Airtable opens up opportunities for more metadata and categorization of assets, like around tracking changes that have occurred over time.

And we were able to build it in under 4 hours, with maybe 50 lines of code total (if you include the JSONata queries). Low code ftw!

Interested in learning a little more about this use case, or think that you may have a similar use case you’d like to build something out for? Get in touch with us. We’d love to talk shop and help you get set up on the right path.

More Use Cases