Technical Articles
Dressing up your VCAL in LMS
Introduction
Many years ago (more than I care to count), I was in a role where I managed blended learning programs. This would include sending out calendar invites to all the participants I was expecting to attend. In my somewhat bias opinion, they were well written and communicated the necessary information. Nothing fancy, but easy to read and to the point. On average, there were 75 people on the “required” list, and maybe 40 or so would show up. I would then be left to reach out to the absentees, find out why they didn’t attend, and develop a plan to catch up.
One day, I decided to dress the invites up a little by adding a banner image across the top. The image was of a conference room table and some chairs, one of which was pulled out from the table, turned towards the viewer. It had a caption … “We’ve saved a seat for you!”.
An interesting thing happened. Upon sending out this newly dressed up invite, I immediately started getting responses.
“Thank you for saving me a seat, but I have a conflict today, when can I make this up?”
“Thank you for thinking of me, I’ll be OOO that day.”
“Unfortunately, I’ll be on Jury Duty next week”.
Seldom would people proactively tell me that they were unable to attend a class. Having advance notice meant I could better set the instructors expectation on the number of attendees and certainly saved me a lot of time in follow up work, and was greatly appreciated. Clearly, the decision to dress up my calendar invites prompted a different (and positive) behavior in our learners.
In this blog, I’ll describe at a high level, how to modify the VCAL entry to support HTML in SuccessFactors LMS. This will allow you to dress up your calendar invites, and hopefully have the same positive experience I did.
Getting down to the details
How do I know what notification to use, if it has options for a VCAL, and what Tokens I can use?
The first stop is SAPs Help Portal. Specifically the “Template ID to Trigger to Receiver Map” found here. I’ve always found this a helpful tool to determine what templates there are, when they are triggered, and who gets them.
Once you’ve identified the template you think you’d like to use, you can check if it has a VCAL option by looking the template up under System Administration » Manage Email » Email Notification Templates. When you’ve opened the template, check the Messages tab. If there is a Message ID labelled “VCAL”, you’ve got yourself a winner !
NOTE: We will not be using the WYSIWYG editor in these instructions. The code we are looking at, and will be setting, is in the VCAL Message field, as seen below.
VCAL Message ID
What syntax Tags are supported?
For a complete list of Syntax Tags that are supported in notifications, first check
System Administration » Manage Email » Email Notification Templates
Search for (and view) the notification that has the VCAL you are modifying. On the Summary tab, there is a Token Set ID.
For example, the SystemEnrollmentNotification templates, uses the ENROLLMENT token set.
Now that you have the Token set ID, lets take a look at what tokens are available.
System Administration » Manage Email » Email Notification Token Sets
There is a limited amount of Tokens sets, so there is no Search Selector for them. You may need to expand your list to show all, or page through until you find ENROLLMENT. View the token set to get a complete list of available tokens.
The Defaults
Lets take a look at the default configuration.
BEGIN:VCALENDAR
METHOD:REQUEST
<LOOP>
BEGIN:VEVENT
UID:<ESCAPEFORVCAL value="<&VCAL_UID>"/>
SEQUENCE:<ESCAPEFORVCAL value="<&VCAL_SEQUENCE>"/>
ORGANIZER:<ESCAPEFORVCAL value="<&VCAL_ORG>"/>
SUMMARY:<ESCAPEFORVCAL value="<&VCAL_SUM>"/>
LOCATION:<&VCAL_LOCN>
DESCRIPTION:<ESCAPEFORVCAL value="<&VCAL_DESC>"/>
DTSTART:<&VCAL_DTSTART>
DTEND:<&VCAL_DTEND>
BEGIN:VALARM
TRIGGER:PT15M
ACTION:DISPLAY
END:VALARM
END:VEVENT
</LOOP>
END:VCALENDAR
This code generates a calendar invite that looks something like this:
Default Calendar Invite
Fairly plain and straight forward. What if I told you, this was possible?
Calendar Invite Generated by LMS
I won’t go through all the line by line code necessary to generate this (that’s not the point of the blog), but I’ll tell you what settings you need to add/change to support adding your own custom HTML.
The Magic you’ve been waiting for
Supporting HTML in the body of the calendar invite requires only two additional lines of code to the VCAL Message.
- VERSION: 2.0
Add this line immediately under the first, as seen below. That’s all there is to the first part. Nothing additional to add to this line. - X-ALT-DESC;FMTTYPE=text/html:
This line can be added anywhere after the first LOOP and before the closing </LOOP> tags. However, I find adding it before/after to the plain text “Description” field to be a good practice. Anything after the colon will be processed as HTML. So start with your opening <html> tag, and start writing your HTML here. Then, as good practice dictates, close your html with </html>. You have full access to all the HTML in between, except things like Javascript and linking to External CSS. Generally, these are unacceptable to most email servers, security, etc. Certainly, this does not prevent you from creating great emails and calendar invites. You’ll see in the Tips section, I recommend using in-line CSS for exactly this reason.
HTML code (tables, color, inline css, etc) will not work in the text DESCRIPTION field. The X-ALT-DESC parameter provides a method to add HTML to an event description. Although considered experimental, this field has become the method of choice when including HTML in a description. When using HTML, both fields must be included so that iCalendar readers that do not support the X-ALT-DESC field can still read the text version.
BEGIN:VCALENDAR
VERSION:2.0
METHOD:REQUEST
<LOOP>
BEGIN:VEVENT
UID:<ESCAPEFORVCAL value="<&VCAL_UID>"/>
SEQUENCE:<ESCAPEFORVCAL value="<&VCAL_SEQUENCE>"/>
ORGANIZER:<ESCAPEFORVCAL value="<&VCAL_ORG>"/>
SUMMARY:<ESCAPEFORVCAL value="<&VCAL_SUM>"/>
LOCATION:<&VCAL_LOCN>
X-ALT-DESC;FMTTYPE=text/html:<html><body> ... <h1>This is a header</h1><br/>This is a label in italics:<i> <label key="notification.Enrollment.MessageText5"/></i><br/>And the SChedule Component tag in bold:<b> <&SCHD-CPNT></b></body></html>
DESCRIPTION:Hello <&STUD-FIRST> <&STUD-LAST>, \n\n You have successfully '<&STUD-ENRL-STATUS>' in this class. You can still put some better verbiage here .. and use \n to indicate a new line.
DTSTART:<&VCAL_DTSTART>
DTEND:<&VCAL_DTEND>
BEGIN:VALARM
TRIGGER:PT15M
ACTION:DISPLAY
END:VALARM
END:VEVENT
</LOOP>
END:VCALENDAR
If you’d like to clean up the plain text version of your calendar invite, then you can certainly do that as well. You can add syntax tags above and beyond what is there by default, using \n for a new line. I’ve included a simple example of this in the code box above.
Tips
Before I send you off writing your HTML, I wanted to share a few tips I learned while developing the same invite you saw above.
- I have found the best way to identify what data comes in what syntax tags, the first thing I did was to put ALL the tags into the body of the email and/or VCAL, then trigger the email. Then I would know which ones I wanted to use, based on the return value.
- While it is technically allowable to have your HTML code span multiple lines in your VCAL, I would not recommend this. There are specific requirements on each line to support this, and its very easy to miss one. Yes, this will result in a VERY long single line of HTML, but still valid. Don’t worry, your email client will be able to read this just fine.
- use inline CSS. This is a good practice not just for VCALs but also when modifying all emails.
- Store images publicly (not behind something requiring authentication, and reference them using the <img> tag. There is an alternative method using base64 encoding, however, as I have yet to test that, I’ll save it for another blog.
- Syntax Tags that might contains multi-line values (meaning could have a hard return in them), like <SCHED_INSTRUCTIONS>, will need to be escaped.
ie: <ESCAPEFORVCAL value=”<SCHED_INSTRUCTIONS>”/>
Summary
In summary, we looked at
- Where / How to find templates
- where to find the tokens that are supported for a given template
- what the default code looks like
- the two lines you need to add to support HTML in your VCAL.
- Tips & Tricks to avoid headaches when you get started.
Chris, great suggestions for what are the plain OOTB notifications in SF Learning. As you pointed out with your opening story, User Experience is paramount in gaining interaction. Thanks for providing these invaluable tips!
Having tried this we don't seem to get any HTML formatting appear in outlook. Is it possible to share the full code?
Also wondering if this can be used with labels so it can appear translated?
Many thanks,
Ben
Hi Ben
Great question! Yes, the VCAL does support Labels. I've updated the code section in the original blog above to include an example syntax tag, a label, and some very basic HTML. I've also tested this code in a demo environment, and is working as expected, with Outlook as the email client. Hope this helps!
thanks
Chris
Dear Chris,
Thnx very much for this explaination and examples!
When I copy/paste your coding (from BEGIN until END) above, I only see the line X-ALT-DESC appearing. See screenshot below:
Do you have any idea?
Best regards,
Mirjam
Hi Mirjam
Looks like it is working as expected. The sample I provided is only a very basic sample showing HTML code that bolds, italicizes text, and how to use labels and syntax tags inside the X-ALT-DESC line.
Next steps would be to continue to extend the HTML code in that line to create even nicer VCALs!
Chris
Chris, I simply love it. Many kudos :-)....
though still a few questions:
DESCRIPTION:<ESCAPEFORVCAL value=<SCHED_INSTRUCTIONS/>/>
X-ALT-DESC;FMTTYPE=text/html:<html><SCHED_INSTRUCTIONS/></html>
But that does not work for us either...
I can see
Brgds., Uwe
Hi Uwe
You can see all labels for the entire LMS (including those used in emails) under
References --> Manage Labels --> Labels.
In the screenshot below, I've searched (and started editing) the label ID notification.Enrollment.MessageText5 (since you use this one as the example in your question).
The LMS substitutes in the text provided based on the recipients language preference. In your LMS user Preferences, you probably have the preferred language set to German, so you received that portion of the email in German.
Editing a Label
There are two things I will mention here:
On your second question .. the DESCRIPTION line is for plain text only. Because your email reader supports HTML, it rendered the code provided in the X-ALT-DESC line instead. Had you been using some type of email reader that does not support rendering HTML, then the plain text in the DESCRIPTION line would be rendered instead (and thus display "Hello ... ").
You should include similar information in both the X-ALT-DESC field and the DESCRIPTION field so that all your users receive the same information.
Thanks again, Christ. Now I think I got it.
After using successfully your example code, I tried to get the registration text tag in the HTML part. But it didn't work. The HTML part was complete empty in the notification / vcal.
Do you maybe see any mistake?
Brgds., Uwe
BEGIN:VCALENDAR
VERSION:2.0
METHOD:REQUEST
<LOOP>
BEGIN:VEVENT
UID:<ESCAPEFORVCAL value="<&VCAL_UID>"/>
SEQUENCE:<ESCAPEFORVCAL value="<&VCAL_SEQUENCE>"/>
ORGANIZER:<ESCAPEFORVCAL value="<&VCAL_ORG>"/>
SUMMARY:<ESCAPEFORVCAL value="<&VCAL_SUM>"/>
LOCATION:<&VCAL_LOCN>
X-ALT-DESC;FMTTYPE=text/html:<html><body><br/><SCHED_INSTRUCTIONS/> <br/></body></html>
DESCRIPTION:Hello <&STUD-FIRST> <&STUD-LAST>, \n\n You have successfully '<&STUD-ENRL-STATUS>' in this class. You can still put some better verbiage here .. and use \n to indicate a new line.
DTSTART:<&VCAL_DTSTART>
DTEND:<&VCAL_DTEND>
BEGIN:VALARM
TRIGGER:PT15M
ACTION:DISPLAY
END:VALARM
END:VEVENT
</LOOP>
END:VCALENDAR
Hi Uwe
Your code is perfect. I would say to double check that the class you registered for during your test in fact, has some test in the Registration text filed, AND for your particular language of preference as well.
Navigate to the specific class you enrolled/registered for.
Click on the "Email Notifications" tab, then in the "Edit Registration Text" section, you'll see an "Edit" hyperlink, that will pop open a WYSIWYG editor. Make sure all the languages configured have something in their respective placeholder. There might very well be something in the English part, but hasn't been translated to other languages.
This is the spot that the <SCHED_INSTRUCTIONS> syntax tag pulls from, and is by default, empty.
Registration Text
Hi Chris, thanks for your time and input.
Registration Text had been filled in all languages and - to be on the safe side - on Class as well as on item level. 🙂
I also used again your example code and it worked.
Then I replaced only the tag, so exchanged <&SCHD-CPNT> for <SCHED_INSTRUCTIONS>.
But it didn't go through:
The tag itself works when i use
DESCRIPTION:<ESCAPEFORVCAL value="<SCHED_INSTRUCTIONS/>"/>
Of course it then displays the registration text as "text only".
Overall, that is strange, isn't it?
Bye, Uwe
Hi Uwe
This does indeed, seem strange. Prior to replying, I set up your exact scenario.
Here is the one line from my VCAL. Note that I've inserted <SCHED_INSTRUCTIONS/> inside the body, before the header (h1) line.
This is for the same Class that was previously show in the screenshot (including my spelling mistakes!)
SCHED_INSTRUCTIONS Result
I got it, thanks a lot, really! My mistake 🙂 .....
The tag seems to get only the first line of the registration text. And I started my registration text with a break. So probably it worked all the time and showed me "a break". So now I deleted the break and put all the registration text into one line and now I can see it all and start working on nicer formatting....
Thank you very, very much! Brgds., Uwe
Hi Uwe
No mistake! I should have see this first, my apologies. Any syntax tag that is multi-line, will need to be escaped. I tried this in my demo environment, and was able to get multiple lines of formatted/html text from that field to show.
Chris
Hi Chris,
as always: many thanks - you spend so much time on my questions.... kudo kudo
First I tried:
<html><body>"<SCHED_INSTRUCTIONS/>"</body></html>
, but that did not work, it only showed the first line, preceeded by a quote.
Then I saw that you suggested:
<html><body><ESCAPEFORVCAL value="<SCHED_INSTRUCTIONS/>"/></body></html>
and that worked nicely. So: Great!
Just being curious: Is there conceptually a difference between using only
<SCHED_INSTRUCTIONS/>
or using
<ESCAPEFORVCAL value=<SCHED_INSTRUCTIONS/>/>
in the X-ALT-DESC part?
And I realized that this tag brings the registration text in the Class only. It does bring the registration text of the item, right? So it is not inherited from the item... Right?
Best Regards and many thanks!
Uwe
Hi Uwe
Glad it is working now!
It does not seem to apply to the SCHED_INSTRUCTIONS tag, at least that is what my initial testing shows .I modified the text on the Item, and created a new class. It did not get copied down. Then I registered for the new class, and did not get anything in the SCHED_INSTRUCTIONS, so it would seem that tag does not roll up to the item.
The documentation on the other hand, suggests there is SOME inheritance from the item.
Ref: https://help.sap.com/viewer/5fae31b1299d4033b665edabea7b9087/2111/en-US/29e11decbe614d0e9a30bec9b85b7302.html
Cheers!
Chris
This is all quite interesting 🙂
I also created a complete new item.
Then I added a registration text.
Then I scheduled the item.
Then I registered.
And: I got the registration text in the VCAL.
And more interesting: First I opened the invitation on my smartphone - and the VCAL did show the registration text including the HTML code as text.
Later I opened the vcal on my laptop. There the registration text was nicely formatted according to my HTML.
And after that I also saw the nice HTML format on my smartphone... strange...
Have a nice day, Uwe
Awesome Chris, can't wait to try this.
Rhonda
Hi Chris Stiles
I would like to only send the calendar invites and avoid the separate/duplicate email per segment. Is there any way to do so? I noticed if I remove all content from the BODY template block, it will no longer send the email and no longer send the calender invite either...
It doesn't make sense to have both the message email and an invite email. With multiple segments, this quickly becomes an annoyance. If you organize a meeting yourself, you send the invite containing some description of the event.
I'm also looking for a way to modify the VCAL so that Outlook does not show the RSVP options, but I havent' found a way to do so.
Edit: deleting the BODY content does seem to work. I'm still receiving the invite (this trick doesn't work if you use ICS apparently).
Best regards,
Pieter
Hi Pieter Janssens
Glad removing the BODY worked out for you! (and correct, this would not work for ICS attachments)
As for removing RSVP options, I'm not sure I understand the request. When LMS sends outlook calendar invites, there is Accept, Decline, or Tentative, but no option to send RSVPs.
See below as an example of the buttons available on the calendar invite sent from LMS. I can accept, but not send response to anyone. Are you seeing something different?
No RSVP options
Hi Crhis,
No, exactly the same, but giving these options is confusing as the participant might think he is 'allowed' to decline. In reality the tentative/decline options will never be registered anywhere else but on the recipients account.
If you create a new meeting request using Outlook, there is an option to not request an RSVP: underneath "Response Options" uncheck "Request Responses". This will then show up in the calendar and instead of 'Accept/Tentative/Decline' it will show 'No response required'.
I've tried using ATTENDEE;CN="XXX";RSVP=false:mailto:"xxxx", but this had no effect.
Best regards,
Pieter
Hi Pieter
I was looking into the ATTENDEE parameter as well, and from what I have read, setting RSVP=FALSE removes the buttons that actually send the response back (seen below in a standard calendar invite), but not the Accept/Tentative/Decline buttons.
Given that the RSVP buttons are missing by default, I'm inclined to think that LMS might be inserting the ATTENDEE line automatically.
I'll keep looking, but I don't think this will be possible.
Chris
Chris
Hi Chris,
Thanks a lot for this blog, really helpful.
We are currently in the process of setting up Microsoft Teams Integration with VLS.
User Emails received:
The email notification template is VLE_ENROLLMENT (VLE Registration Notification Email Template) – This notification is sent to user(s) when user registers for the class. This email has the MS Teams URL to join the online event.
Also, an email notification with below details. URL is being generated to join the online event.
Meeting Key:
Meeting Password:
Session Details:
Click on the following URL to join the online event:
Also, an Training Registration Confirmation Notification Email. This email has .ics attachment and when we click on it, we can add the calendar invitation to the outlook. The .ics attachment does not have any URL / Meeting link. This .ics attachment when added to the calendar invitation to outlook it shows up in MS Teams Calendar however this MS Teams Calendar does not have the URL/meeting link to join the meeting / class.
The email notification with the calendar invite did not include the MS Teams link.
Is it possible if the MS Teams link can be directly accessed via calendar invite instead of only receiving a reminder via the calendar and having to access Learning, find the course to start the course?
Regards,
VP.
It is mainly with the System Enrollment Notification. Under VCAL section there is no token for URL.
This VCAL Section is shown as .ics attachment in the email received.
Since there is no URL / Meeting link (STUD_URL) token, when added to the calendar invite, it does not show the meeting link / URL for users to join.
Hello Chris !
Thanks a lot for this very helpful tips !!
I also have a little question about the way some tokens are diplayed and the planning & the address in particular.
Address :
Belgolaise
Cantersteen
Bruxelles
1000
Config :
DESCRIPTION:<ESCAPEFORVCAL value="Adress :
<&SEG-FACILITY>
"/>
2. When I using the HTML solution, all the rest of the email is nicer, but both those tags come in one line, like this :
Adress : Belgolaise Cantersteen Bruxelles 1000
Config :
X-ALT-DESC;FMTTYPE=text/html:<html><body>- Adress : <ESCAPEFORVCAL value="<&SEG-FACILITY>"/><br/></body></html>
It's not a big deal when I have only one adress, but some training are divided in different segments, which are organised in different places. When you have different places, it's not very nice... For example :
Adress : Atrium Rue des Colonies 62 Koloniënstraat Bruxelles 1000 Belgolaise Cantersteen Bruxelles 1000 Delta Bd des Invalides 224 Invalidenlaan Bruxelles/Brussel 1160
=> Not very clear for the end-user 😉
First of all, I think the adress mentionned on the VCAL should be the one liked to the particular segment, and not all of them (it really makes no sense...).
So my question is : is it possible to make it appear like this :
Adress :
Atrium Rue des Colonies 62 Koloniënstraat Bruxelles 1000
Belgolaise Cantersteen Bruxelles 1000
Delta Bd des Invalides 224 Invalidenlaan Bruxelles/Brussel 1160
And I have the same question about the tag <&SEG-GRID>.
Thanks a lot in advance for your help !
V.
Hi V
I actually have the same issue - wondering if there is an easy solution for this.
Chris Stiles any advice on this? How to display the actual spaces in the text?
br
Gina
Violaine Dufranne did you figure that out?
Gina Wangler Violaine Dufranne
Try wrapping the <&SEG-FACILITY> tag with "<pre>" tags. The will preserve the whitespace/new line characters
Sample in code block below.
Hi Chris
Thanks for your reply. For my case with the SCHD-DESC-EDITABLE it worked with the following - I had to define the font because otherwise it had a completely different font than the rest of the text.
Thanks so much!
Hi Chris,
thank you for this great blog post! I tried to adapt your HTML code within the VCAL notification.
I am currently facing some issues with my code and do not find the error. It the VCAL mail notification only shows the text until <&SEG-SUMMARY> (bold marked code).
This is the code:
BEGIN:VCALENDAR
METHOD:REQUEST
<LOOP>
BEGIN:VEVENT
UID:<ESCAPEFORVCAL value="<&VCAL_UID>"/>
SEQUENCE:<ESCAPEFORVCAL value="<&VCAL_SEQUENCE>"/>
ORGANIZER:<ESCAPEFORVCAL value="<&VCAL_ORG>"/>
SUMMARY:<ESCAPEFORVCAL value="<&VCAL_SUM>"/>
LOCATION:<&VCAL_LOCN>
X-ALT-DESC;FMTTYPE=text/html:<html><font size="2" face="arial"><body> <h3><label key="notification.u..enrollment.registration.begin"/></h3><br/><label key="notification.u.salutation"/><br/><br/><label key="notification.Enrollment.MessageText4"/><br/><&SCHD-DESC><br/><&SEG-SUMMARY><br/><&SEG-GRID><br/><&SCHD-DESC-EDITABLE><br/><label key="notification.u.question.contact"/><br/></body></html>
DESCRIPTION:<ESCAPEFORVCAL value="<&VCAL_DESC>"/>
DTSTART:<&VCAL_DTSTART>
DTEND:<&VCAL_DTEND>
BEGIN:VALARM
TRIGGER:PT15M
ACTION:DISPLAY
END:VALARM
END:VEVENT
</LOOP>
END:VCALENDAR
Therefore I have two questions:
Thank you very much! I am look forward hearing from you.
Celin
Celin Mutschler - the <&SCHD-DESC-EDITABLE> token is taking code from a part of the LMS where hard returns are allowed, which is why the VCAL cuts of at that point. You'll need to escape that syntax tag, so that it doesn't have line breaks. This can be done as follows:
Chris
Dear Chris,
thank you very much.
At what place within the code do you place the token? If I replace it with your code its still not within the notification.
Furthermore, is this the reason why the rest of the code is not shown, e.g. <label key="notification.u.question.contact"/>?
Thank you in advance.
Celin
Labels can potentially also contain hard returns. You will need to use the ESCAPEFORVCAL tag on any label or syntax tag that might have a hard return, or as described earlier, wrap the label in "<pre>" tags. In either case, if code is cutting off, it is almost certainly because of a hard return causing the html code to not be on the same line in your vcal.
Hi Chris,
I saw that you were able to put image in your VCAL. When I tried it myself, this happened to me.
Any idea why the image is not displaying.
Thank you.
Hi Brian
In this case, it is Outlook that prevented the download of the image. There is a setting in Outlook users can set (if their Outlook Administrators permit changing settings) to always download images. (Microsoft Article here)
I haven't had time yet to try Base64 encoded images ... might be worth a shot?
Chris
Hi Chris,
Great blog - I wanted to ask, do you know if it's possible to switch off VCAL notifications and just allow the Registration notification to go out. We are wanting to send a calendar invite manually outside of the system.
Thanks,
Mustafa
Hi Mustafa
I haven't tested this, but if you removed the code from the VCAL entirely, it probably won't send. I have seen examples of where incorrect code caused the VCAL to not send, so intentionally removing all the code should be just as effective!
Chris