Hi @Eaglef90 ,
Here is a quick setup you can try:
Step 1: Update your Document Type Add a new Date Picker property to your Document Type with the alias firstPublishedDate.
Step 2: Create the Handler Write a handler that checks if this property is empty, and stamps it if it is. (Note: Modern Umbraco strictly enforces UTC, so always use DateTime.UtcNow).
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;
namespace MyQuickUmbracoSitetestsql10.Notifications
{
public class TrackPublishStateHandler : INotificationHandler<ContentPublishingNotification>
{
private readonly ILogger<TrackPublishStateHandler> _logger;
// Inject the logger
public TrackPublishStateHandler(ILogger<TrackPublishStateHandler> logger)
{
_logger = logger;
}
public void Handle(ContentPublishingNotification notification)
{
foreach (var node in notification.PublishedEntities)
{
// Log that the event fired for this specific node
_logger.LogInformation("==> Publishing event triggered for node: {NodeName} (ID: {NodeId})", node.Name, node.Id);
// 1. Check for First Publish
if (node.HasProperty("firstPublishedDate"))
{
if (node.GetValue("firstPublishedDate") == null)
{
_logger.LogInformation("==> RESULT: Node '{NodeName}' is being published for the VERY FIRST TIME. Stamping UTC date.", node.Name);
node.SetValue("firstPublishedDate", DateTime.UtcNow);
}
else
{
_logger.LogInformation("==> RESULT: Node '{NodeName}' already has a first publish date: {Date}", node.Name, node.GetValue("firstPublishedDate"));
}
}
else
{
_logger.LogWarning("==> WARNING: Node '{NodeName}' does not have a 'firstPublishedDate' property on its Document Type.", node.Name);
}
// 2. Check Previous Publish State
if (node.Published)
{
_logger.LogInformation("==> RESULT: Node '{NodeName}' was ALREADY LIVE. Previous publish date was: {Date}", node.Name, node.PublishDate);
}
else
{
_logger.LogInformation("==> RESULT: Node '{NodeName}' is currently UNPUBLISHED (it is a new draft or was previously unpublished).", node.Name);
}
}
}
}
}
(If you are using Variant/Multilingual content, remember to loop through node.AvailableCultures and pass the culture into the SetValue method).
Step 3: Register in Program.cs Don’t forget to register the handler in your pipeline! In your Program.cs file, attach it to the Umbraco builder:
builder.CreateUmbracoBuilder()
.AddBackOffice()
.AddWebsite()
.AddComposers()
.AddNotificationHandler<ContentPublishingNotification, TrackPublishStateHandler>()
.Build();
How to quickly test this: Save and run your project. Go to the Umbraco Backoffice, create a new page, and hit “Save and Publish”. Look at your custom firstPublishedDate property—you’ll see it automatically populated. If you unpublish, make a change, and publish again, that original date will remain intact.
Hope this helps!