Knut Melvær
Knut is a principal developer marketing manager at Sanity.io
Automatically track when content was first published with a timestamp that sets once and never overwrites, providing reliable publication history for analytics and editorial workflows.
// Add the field to your "post" document type
defineField({
name: 'firstPublished',
title: 'First Published',
type: 'datetime',
readOnly: true,
})// Add this to the `resources` array in your blueprint configuraiton
import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints'
export default defineBlueprint({
resources: [
defineDocumentFunction({
type: 'sanity.function.document',
name: 'first-published',
src: './functions/first-published',
memory: 1,
timeout: 10,
event: {
on: ['create'],
filter: "_type == 'post' && !defined(firstPublished)",
projection: '{_id}',
},
}),
],
})import {createClient} from '@sanity/client'
import {documentEventHandler} from '@sanity/functions'
export const handler = documentEventHandler(async ({context, event}) => {
const client = createClient({
...context.clientOptions,
apiVersion: '2025-07-17',
useCdn: false,
})
const {data} = event
const {local} = context // local is true when running locally
try {
const firstPublishedDate = new Date().toISOString()
const result = await client
.patch(data._id)
.setIfMissing({
firstPublished: firstPublishedDate,
})
.commit({dryRun: local})
console.log(
local
? `(LOCAL TEST MODE - Content Lake not updated) Set firstPublished timestamp for document (${data._id}): ${firstPublishedDate} `
: `Set firstPublished timestamp for document (${data._id}): ${firstPublishedDate}`,
result,
)
} catch (error) {
console.error('Error setting firstPublished timestamp:', error)
}
})
{
"name": "first-published",
"type": "module",
"main": "index.ts",
"dependencies": {
"@sanity/client": "^7.6.0",
"@sanity/functions": "1.0.3"
}
}Content teams need to track when articles were first published for analytics and editorial workflows, but manually setting timestamps is error-prone and often forgotten during the publishing process. This leads to inconsistent data and makes it difficult to analyze content performance over time.
Quick Start
View the complete example and source code
Initialize blueprints if you haven't already: npx sanity blueprints init
Then: npx sanity blueprints add function --example first-published
Then deploy: npx sanity blueprints deploy
How It Works
This function uses Sanity's setIfMissing operation to ensure the timestamp is only set once:
setIfMissingThe key is the setIfMissing operation, which only sets a value if the field doesn't already exist, preventing accidental overwrites.
Key Benefits
Knut is a principal developer marketing manager at Sanity.io
AI-powered automatic tagging for Sanity blog posts that analyzes content to generate 3 relevant tags, maintaining consistency by reusing existing tags from your content library.
Go to Automatically tag blog postsOn document publish, send a Slack notification so your team is informed
Go to Notify your team via Slack on publishCreate, preview, and send Klaviyo campaigns without ever leaving Sanity Studio"
Go to Klaviyo campaigns without leaving your StudioWrite once in Studio. Post everywhere. No copy-paste, no platform hopping.
Go to Publish Once, Post Everywhere