I have created a dynamic url to display a logo image from content document. I uploaded the image and logged into the org and can see the image. When I use an incognito window the link gets broken but my urls look the same. I used ContentVersionId as record Id. What am I missing?


    <apex:image id="theImage" value="/sfc/servlet.shepherd/version/download/{!logoid}" width="300"/>


            urlsContentDistribution = [SELECT DistributionPublicUrl, ContentDownloadURL , name, ContentVersionId  FROM ContentDistribution WHERE RelatedRecordId = :accs[0].id];
        catch(Exception e){
            System.debug('An exception urlsContentDistribution occurred: ' + e.getMessage());

for(ContentDistribution logo:urlsContentDistribution){
           logoId = logo.ContentVersionId;
            system.debug('logoId: '+logoId);

Logged in(renders correctly):


Incognito(Broken link):

  • Are you using the page on force site when you open in incognito? May 25, 2019 at 9:00
  • @rahulgawale Yes, every thing else is shown but I end up with a dummy image.
    – Thomas
    May 25, 2019 at 16:38
  • you need to make the images public. May 25, 2019 at 18:41

1 Answer 1


By default, files visibility is for internal users. You need to create a content document link and content distribution for the file.

If you want the access to all file automatically you need to write a trigger.


trigger ContentVersionTrigger on ContentVersion (after insert) {


public class ContentTriggerHandler {
    public static void createPublicLinkForFile(List<ContentVersion> contentVersions){
        system.debug('in ContentTriggerHandler');
        ContentDocumentLink[] contentDocumentLinks = new List<ContentDocumentLink>();
        ContentDistribution[] distributionsToInsert = new List<ContentDistribution>();
        Set<Id> contentDocId = new Set<Id>();
        for(ContentVersion objContentVersion : contentVersions){

        Map<Id,ContentDocument> contentDocMap = new Map<Id,ContentDocument>([Select id, ParentId From ContentDocument WHere ID in : contentDocId]);

        for(ContentVersion objContentVersion : contentVersions){
                Id parentId = contentDocMap.get(objContentVersion.ContentDocumentId).ParentId;
                if(parentId != null){
                    contentDocumentLinks.add(createContentDocumentLink(objContentVersion.ContentDocumentId, parentId));

        insert contentDocumentLinks;
        insert distributionsToInsert;

    public static ContentDocumentLink createContentDocumentLink(Id contentDocumentId, Id parentId){
        ContentDocumentLink objDocLink = new ContentDocumentLink();
        objDocLink.ContentDocumentId = contentDocumentId;
        objDocLink.LinkedEntityId = parentId;
        objDocLink.ShareType = 'V'; // Inferred permission
        objDocLink.Visibility = 'AllUsers'; //All users
        return objDocLink;

    public static ContentDistribution createContentDistribution(Id contentVersionId){
        ContentDistribution newDist = new ContentDistribution();
        newDist.ContentVersionId = contentVersionId;
        newDist.Name = 'External Link';
        newDist.PreferencesNotifyOnVisit = false;
        newDist.PreferencesAllowViewInBrowser = true;
        return newDist;
  • 1
    I found this solution already only the downside is that it for all inserts, but thanks anyway. Seem there is no other way to do this dynamically. For now I chose to do this trough a static resource. Pitty this cant be done with functional salesforce setting.
    – Thomas
    May 29, 2019 at 6:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .