Take the community feedback survey now.

How is "By"-value saved in version history?

Vote:
 

On my clients site we have external users that we fetch from their CRM and when someone logs in we fetch the information from that CRM and build up our custom User object (that's based on IdentityUser).

My client has noticed though that sometimes the "By" (that is, the person that did the editing) seems to be wrong. Just the other day a crusial page got unpublished and the person that did it (according to Versions history) swear that it wasn't she. 

It could be that it was all just a mistake (many editors aren't that tech savy) but if it's some kind of ID mismatch because if external users it would be nice to correct that bug.

 

#341094
Nov 26, 2025 7:52
Vote:
 

Good question,  thanks for raising this. Below is how I understand “by-value” is handled in version history in Optimizely (and some clarifications + caveats).

 

What version history does under the hood

  • Optimizely CMS tracks versions of content items using a versioning system that implements IVersionable. Each time you save/publish (depending on SaveAction), CMS creates a new version entry.

  • Each version stores all property values of the content item — i.e. each version snapshot stores the content’s properties (strings, numbers, references, component properties, etc.) as they were at the time of save/publish.

  • That means the history record is effectively a deep snapshot by value — not merely a diff or reference to “changed properties only”.

 

Hence when you open version history (or use the “compare versions” / “restore previous version” features) you’re getting exactly the saved state of that version: all property values as they existed then.

 

What “by value” does not mean (or common misconceptions)

  • It does not mean that linked or nested content items (e.g. blocks, referenced media, content-references) themselves get rolled back. Versioning applies per “content item” (page, block, etc.). If your content contains references to other items, version history for that content item will preserve the reference, but not automatically roll back the referenced item’s content. This is consistent with how CMS historically handles versions of content + linked content. (See long-standing discussions around “versioning pages + media/files + referenced content”). 

  • It does not guarantee infinite history — the number of versions retained depends on configuration (MaximumVersions / uiMaxVersions in older CMS versions). If that limit is reached, older versions may be purged.

 

Hope that will helps!

Thanks,

#341097
Nov 26, 2025 8:50
Vote:
 

Hi Sunil

No, not really. It wasn't what I was asking. I'm asking how the user doing the editing is saved (the information that's shown in the "By"-column in version tab). Especially when the user isn't a built in ApplicationUser.

#341099
Edited, Nov 26, 2025 8:58
Vote:
 

Thanks Alexander for the clarification — now I understand what you’re looking for.

The value shown in the “By” column comes from the SavedBy field in the ContentVersion table.
This is always stored as a plain string, not as an ApplicationUser or any other user object.

CMS simply saves the value from:

ClaimsPrincipal.Identity.Name

at the moment the content is saved.
It does not require an ApplicationUser, and there is no foreign key or user lookup involved.

So whatever your authentication/IdP sets as the authenticated user’s Identity.Name is exactly what gets written into the version history.
If Identity.Name is empty, the “By” column will also appear empty.

If you want to control what appears in “By”

You need to map the correct claim into Identity.Name using a claims transformation.
For example:

public class CustomNameClaimsTransformation : IClaimsTransformation
{
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var name = principal.FindFirst("preferred_username")?.Value
                   ?? principal.FindFirst("email")?.Value;

        if (principal.Identity is ClaimsIdentity identity)
        {
            identity.AddClaim(new Claim(identity.NameClaimType, name));
        }

        return Task.FromResult(principal);
    }
}

Database side

The username is stored in:

tblContentVersion.SavedBy

as an NVARCHAR field — no foreign key, no relation to an internal user table.
It’s simply the string provided by your ClaimsPrincipal.

Hope this will helps you!

 

#341100
Edited, Nov 26, 2025 10:21
Vote:
 

Hi Sunil

Awesome, precisely what I was after. Thank you for your help. I'll double check and see if the correct name is fetched.

#341101
Edited, Nov 26, 2025 10:24
Sunil - Nov 26, 2025 10:26
Glad it helped, Alexander — happy to assist!
No worries about accepting the answer; the important part is that you got what you needed.
Vote:
 

Correction, the changed by is stored in tblWorkContent.ChangedByName column, for default CMS content 

#341123
Nov 27, 2025 13:12
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.