Winter '20 Release Note: If you are using S-Docs below version 4.53, you may experience an "Attempt to de-reference a null object" error when interacting with various forms of automation in S-Docs. In order to fix this bug, you can create a new SDocs Settings custom settings set. To do this, type "Custom Settings" into the Quick Find / Search bar in the Setup menu, and click Custom Settings. Click SDocsSettings, then click Manage at the top of the page. From there, click New. Fill out the following information:

Name: SDocsSettings
SD Jobs Batch Size: 30
SD Jobs Move to Top of Flex Queue:

Additionally, ensure that you have a Remote Site Setting for either (production), or (sandbox).

Note: This guide builds on automation features discussed in the one-click and zero-click guide (Automation Options Improving Efficiency and Compliance).


With the use of Salesforce logic in the S-Docs button URL, you have an endless amount of possibilities for automating template selection and generation. You can easily modify the standard S-Docs button code so that when users click the button, S-Docs will automatically select or generate certain documents depending on the values in a record’s fields.

For example, suppose that we have multiple templates for a letter sent to contacts, and that this letter will vary depending on what a given contact’s department is. If the variation is small, we could handle this using render statements. But suppose these were completely different letters requiring completely different templates, and we don’t want to require our sales team to memorize the contact’s department, click the S-Docs button on the contact record’s page, and then have to click the appropriate letter template prior to document generation. We’d rather have a user in our org just click S-Docs and be immediately taken to their templates.

We can accomplish this by editing an object’s existing S-Docs button, or creating a new button if you’d like users to have the option of using the normal S-Docs button in case they need to manually select templates. In this case, we’ll go with the first choice, and simply edit our existing S-Docs button.

Using The Doclist Parameter

In the following sections, we will be automatically selecting documents with the doclist Apex parameter. To use this, we simply append the following to our S-Docs button code:


Note: If you have multiple templates with the same name, they will all generate if one of them is referenced by this parameter.

You can also use template IDs for the doclist parameter, however this is not recommended because these IDs will change between sandbox and production orgs, meaning that you will have to re-add the new template IDs into this parameter after transferring to production.

The doclist can include as many S-Doc templates as you’d like. If you just append the doclist parameter, templates will be automatically selected and generated. If you would like your S-Docs templates to be automatically selected, but not automatically generated, you can append oneclick='false' to your S-Docs button code as well, as this parameter modulates the doclist parameter. For a full list of button parameters, please visit our Apex Parameter documentation.

Two Outcomes: True or False (IF Function)

Let’s suppose that members of every department except finance gets letters derived from the same template, and the finance department gets letters derived from a different, special template. This means that we have two outcomes to consider in our automatic template selection: the contact is in the finance department, or the contact is in some other department. So, we handle this with the doclist Apex parameter and an IF function that determines the templates to be included in the doclist. The button URL would look like this:

We see that if the contact’s department is “Finance,” then the template will be "Finance_Letter," which happens to be the S-Docs template for our special finance department letter. However, if the contact’s department is not “Finance,” then the doclist parameter will be "All_Depts_Letter," which is the template for our letter for all other departments.

More Than Two Outcomes (CASE Function)

Now suppose that members of technology departments will also receive a totally different letter. This means we can’t use an IF function, as we now have three outcomes; the contact could be in the finance department, the technology department, or in some other department. This means we’ll have to use the CASE function instead. The button URL would look like this:

We see that the finance department will get their own letter, the technology department their own letter, and since else_result is “All_Depts_Letter," all other departments will receive letters derived from the same template.

Building a Doclist with Multiple Functions

Now, suppose that we’d like to send an account’s primary contact a questionnaire regarding how much they like our product. Additionally, suppose we have two true/false fields: Up_For_Renewal__c and Receives_Discount__c, which respectively denote whether the account is up for renewal and whether the account is eligible for a discount. We’re sending the account’s primary contact the questionnaire no matter what, and depending on the status of the other two fields, we may or may not send a letter informing them that they are up for renewal, and possibly some kind of coupon code or voucher if they are eligible for a discount. Let’s say the questionnaire template is named "Questionnaire_Template," the up-for-renewal template is named "Renewal_Letter," and the coupon code template is named "Coupon_Code."

Then, we could accomplish this with the following button URL:

Since we’re sending the questionnaire no matter what, its template name is at the front of the doclist outside of the IF function. Then, we have two IF functions that will return a template (each of which is preceded by a comma, since our doclist must be comma-delimited without spaces) if their respective fields are true. So, if Up_For_Renewal__c and Receives_Discount__c are both true, our resulting doclist will be:

If  Up_For_Renewal__c is false and Receives_Discount__c is true, our resulting doclist will be:

If both of these fields are false, our resulting doclist will be:

In the last case, this is because value_if_false for our two IF functions is an empty string (specified as two quotation marks with nothing between them). Don’t worry about the additional commas; S-Docs will ignore these and just generate the document with the template name Questionnaire_Template. We could place commas inside of our code’s quotation marks such that they would always yield clean-looking doclists. However, this might take a bit more thought and work to write, and could be more prone to mistakes (or you might think the opposite; it’s a matter of personal preference). No one’s really looking at the resulting doclist after your IF functions evaluate; it’s just used internally by S-Docs to find which templates to use. So, you don’t need to worry about what your doclist evaluates either, as long as the logic is correct and there is at least one comma between each template name whenever the doclist evaluates.

Nested IF Functions

Our code’s structure in the previous example is very useful in plenty of cases. However, it might not make sense to send an account a coupon code along with the questionnaire if they aren’t up for renewal. We might want to send that coupon code only if they’re up for renewal. We can accomplish this using a nested IF function:
Let’s take this statement apart. Our questionnaire’s template name, Questionnaire_Template, will be on our doclist no matter what. Now, what happens if Account.Up_For_Renewal__c is true? First, note that we included a comma at the end Renewal_Letter; this comma is inside the string, since we don’t want to confuse our IF function with extra commas laying outside the string. We then followed this string with an ampersand (i.e. the concatenation operator) and a nested IF function. Whatever the nested IF function returns will be concatenated to the end of the following string: Renewal_Letter.

So, if Account.Up_For_Renewal__c is true, and Account.Receives_Discount__c is false, our resulting doclist will be:

Then, if Account.Up_For_Renewal__c and Account.Receives_Discount__c are both true, our resulting doclist will be:

And finally, if Account.Up_For_Renewal__c is false and Account.Receives_Discount__c is true, our resulting doclist will be:

In other words, accounts will receive just the questionnaire if they aren’t up for renewal, even if they are eligible for the discount. No need to jump the gun on that coupon code!

Using AND/OR Functions

AND/OR functions can be used with the doclist parameter as well. For example, say we become big fans of small business and decide to create a promotional period in which accounts with annual revenues less than $100,000 will also receive a coupon code, even if Account.Receives_Discount__c is false. To accomplish this, we can place an OR function inside of our IF function: