Preserving image filenames in Sanity CDN URLs for SEO visibility

6 replies
Last updated: Apr 28, 2021
Hey everyone 👋 long-time lurker, first-time poster. I’ve been building sites and templates with Gatsby/Sanity together for a while now and along the way a fair few clients have asked me how to preserve image filenames in generated CDN URLs for SEO visibility. I’ve got as far as manipulating the
originalFilename
, but I can’t find anything on how Sanity manages filename generation when exporting imagery out to and hosting on the CDN. If anyone has any experience in this realm your help or advice would be much appreciated
AI Update

Great question! You're on the right track with originalFilename – this is exactly what you need for creating SEO-friendly image URLs.

Sanity supports what they call "vanity filenames" which lets you append a human-readable filename to the end of the hashed image URL. This gives you the SEO benefits you're looking for without changing how the CDN fundamentally works.

How Vanity Filenames Work

The CDN URL format is:

https://cdn.sanity.io/images/<projectId>/<dataset>/<hashedFileName>/<vanityFilename>?<params>

So instead of:

https://cdn.sanity.io/images/1234567/production/754c8d64997b668642bd2500f833722c6293cf8b-1766x1065.png?q=75&fit=clip&auto=format

You can have:

https://cdn.sanity.io/images/1234567/production/754c8d64997b668642bd2500f833722c6293cf8b-1766x1065.png/my-product-image.png?q=75&fit=clip&auto=format

The hash stays in the URL (it's required for the CDN's content-addressable architecture), but you get the human-readable filename at the end, which is what search engines care about.

Implementation with Gatsby

For Gatsby specifically, you'll need to:

  1. Query the originalFilename field from your image assets in your GraphQL queries:
query {
  allSanityYourType {
    nodes {
      image {
        asset {
          url
          originalFilename
          # other fields you need
        }
      }
    }
  }
}
  1. Append the filename when building your image URLs. If you're using gatsby-plugin-image or @sanity/image-url, you'll need to manually append /${originalFilename} to the generated URL.

Here's a practical example:

import imageUrlBuilder from '@sanity/image-url'

const builder = imageUrlBuilder(sanityConfig)

function urlFor(source, originalFilename) {
  const baseUrl = builder.image(source).url()
  return originalFilename ? `${baseUrl}/${originalFilename}` : baseUrl
}

// Usage:
const imageUrl = urlFor(image.asset, image.asset.originalFilename)

Important Notes

  • The vanity filename doesn't have to match the originalFilename – you can use any SEO-friendly name you want, or even add a custom field to your image schema for this purpose
  • All the usual image transformation parameters (format, quality, dimensions, etc.) continue to work normally
  • This feature isn't extensively documented yet (as mentioned in this community answer), but it's fully supported by the CDN

The hash-based filename is actually a feature, not a bug – it enables Sanity's content-addressable storage system where the URL itself is derived from the content, making cache invalidation automatic and bulletproof. The vanity filename gives you the best of both worlds: reliable caching and SEO-friendly URLs.

Hi
user H
👋 The CDN lets you add 
/someFilename.jpg
 at the end of an image/file URL, while still working with the usual parameters (and things like webp format support).
This should allow you to add the
originalFilename
(or any other field you’ve prepared for this) at the back of a URL as follows:
<https://cdn.sanity.io/images/><projectId>/<dataset>/<hashedFileName>/<originalFilename>?<params>
Does that help?
Thank you, that’s really good to know! Are you able to confirm if the images including the
originalFilename
are indexed by Google?
For example:

<https://cdn.sanity.io/images/><projectId>/<dataset>/98767cd8f798987.../Cats-in-suspicious-clothing.jpg?w=800&h=450&fit=crop
^ If I search for “cats in suspicious clothing”, am I likely to find some variant of this Sanity CDN-hosted image?
Never mind, I wrote a component that inserts the original filenames into fluid URLs. End result is that the full filename is available in the src/srcset &lt;img&gt; attributes, but the images look and work the same as they did. Thanks for the help!
Awesome intel here pals! 🙏
user M
Is there a way to add
/someFilename.jpg
when using Gatsby image?
user A
You could enrich your fluid URLs with
/someFilename.jpg
(as
originalFilename
), e.g.
  const {
    asset: { fluid, description, originalFilename, title }
  } = image; // Sanity image data

  const fluidKeys = Object.keys(fluid);
  const fluidEnriched = {};

  if (fluidKeys?.[0]) {
    fluidKeys.forEach((fluidKey) => {
      let value = fluid?.[fluidKey]?.toString();

      if (value.includes(`.jpg`)) {
        value = value.replace(/.jpg/g, `.jpg/${originalFilename}`);
      } else if (value.includes(`.png`)) {
        value = value.replace(/.png/g, `.png/${originalFilename}`);
      } // other filetypes

      fluidEnriched[fluidKey] = value;
    });
  }
Then

import Img from "gatsby-image";

<Img fluid={fluidEnriched} />

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?