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? – rahul gawale May 25 '19 at 9:00
  • @rahulgawale Yes, every thing else is shown but I end up with a dummy image. – Thomas May 25 '19 at 16:38
  • you need to make the images public. – rahul gawale May 25 '19 at 18:41

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;
| improve this answer | |
  • 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 '19 at 6:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.