Sitecore Multi-site Multi-CDN implementation

Recently we have been going through a series of SEO tweaks based on recommendations from our SEO Expert. Several of them are very interesting to look into and the reasoning and how search engines rank sites based on that is amazing.

One of those happens to be how we use a CDN. CDN stands for Content Delivery Network. A CDN helps deliver anything from web page assets to the page itself to the end users browser. In our case we use a CDN for our website assets like CSS, java-script and media library items.

This works fine as the server url is added to all the media library links. Now, if we have multiple sites, we would want to control the CDN accordingly. Also based on the SEO guidelines its better to do cdn.SiteA.com or anysubdomain.SiteA.com for the CDN name.

So now we need to use cdn.SiteA.com and cdn.SiteB.com on the same instance of Sitecore where we have only one setting which is Media.MediaLinkServerUrl. To get around this we turn to the MediaProvider. We would need to override the GetMediaUrl function to append the appropriate CDN host based on the website.

There are a few CDN modules on the Sitecore marketplace but we wanted something simple. We want it to just modify the Media Library links and append the url of the CDN per site. To do this, we add an additional attribute to the site node of your website to store the CDN hostname.

XHTML

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">

<sitecore>

<sites>

<site name="firstsite"patch:before="site[@name='website']"

virtualFolder="/"

physicalFolder="/"

rootPath="/sitecore/content/firstsite"

startItem="/Home"

database="web"

domain="extranet"

allowDebug="true"

cacheHtml="true"

htmlCacheSize="5000MB"

xslCacheSize="10MB"

filteredItemsCacheSize="20MB"

enablePreview="true"

enableWebEdit="true"

enableDebugger="true"

disableClientData="false"

hostName="firstsitedomain*"

cdnHostname="cdn.firstsitedomain.com"

/>

<site name="secondsite"patch:before="site[@name='website']"

virtualFolder="/"

physicalFolder="/"

rootPath="/sitecore/content/secondsite"

startItem="/Home"

database="web"

domain="extranet"

allowDebug="true"

cacheHtml="true"

htmlCacheSize="5000MB"

xslCacheSize="10MB"

filteredItemsCacheSize="20MB"

enablePreview="true"

enableWebEdit="true"

enableDebugger="true"

disableClientData="false"

hostName="secondsitedomain*"

cdnHostname="cdn.secondsitedomain.com"

/>

<!-- Third site does not use a CDN -->

<site name="thirdsite"patch:before="site[@name='website']"

virtualFolder="/"

physicalFolder="/"

rootPath="/sitecore/content/thirdsite"

startItem="/Home"

database="web"

domain="extranet"

allowDebug="true"

cacheHtml="true"

htmlCacheSize="5000MB"

xslCacheSize="10MB"

filteredItemsCacheSize="20MB"

enablePreview="true"

enableWebEdit="true"

enableDebugger="true"

disableClientData="false"

hostName="thirdsitedomain*"

cdnHostname=""

/>

</sites>

</sitecore>

</configuration>

Once that is done you would need to create the following class called CDNMediaProvider inheriting from the MediaProvider class.

The code above can serve requests as they come and cache them for a speedy retrieval. As you can see I am adding in the version and the updated date so that published changes will get reflected. To get this code executing we need to register our CDNMediaProvider class using the following patch config.

That is it. Once the code is published with the right settings, you will see your media urls come up with the cdn host appended.
https://cdn.firstsitedomain.com/-/media/hero/blackboard.png?v=1&d=20170322T200703Z

If you have any questions or concerns, please get in touch with me. (@akshaysura13 on twitter or on Slack).

This is a personal blog. Any views or opinions represented in this blog are my own and do not represent those of people, institutions or organizations that the I may or may not be associated with in professional or personal capacity including past, current and future employers, unless explicitly stated.