You are usually adding new publishing targets in Sitecore because of different geographic regions or databases in different data centers where you are hosting these web databases.

For a long time, for Sitecore 7 and 8, process for creating new publishing target was more or less the same. You have created new entry in ConnectionStrings.config, added new <database> entry in web.config and added new definition item in master database under “/sitecore/system/Publishing targets” node.

In Sitecore 9 process has been slightly changed. You are not changing web.config anymore but Sitecore.config and 2 additional steps are now involved for adding new publishing target. These two more steps are adding <eventQueue> and <PropertyStoreProvider> elements in Sitecore.config.

In my example below, I will use “web_secondary” as name of publishing target database. I will use “QA” as name of publishing target.

Steps to add new publishing target in Sitecore 9:

  1. Create new target database in ConnectionStrings.config where you want content to be published:
    <add name="web_secondary" connectionString="Data Source=.\;Initial Catalog=webdbname;User ID=user ID;Password=Password" />
  2. Add new entry in master database under “/sitecore/system/Publishing targets” node. PublishingTargets02PublishingTargets03
  3. Create a patch file under C:\inetpub\wwwroot\instancename\App_Config\Include\Project\ or any other folder based on your setup. I have named my patch config file “PublishingTargets.config” and this is it’s content (you can just copy it and change web_secondary based on name of your secondary web database specified in ConnectionStrings.config):
 <?xml version="1.0" encoding="utf-8" ?>
 <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
     <sitecore>
         <eventing defaultProvider="sitecore">
            <eventQueueProvider defaultEventQueue="core">
                <eventQueue name="web_secondary" patch:after="eventQueue[@name='web']" type="Sitecore.Data.Eventing.$(database)EventQueue, Sitecore.Kernel">
                     <param ref="dataApis/dataApi[@name='$(database)']" param1="$(name)" />
                     <param hint="" ref="PropertyStoreProvider/store[@name='$(name)']" />
                </eventQueue>
            </eventQueueProvider>
         </eventing>
         <PropertyStoreProvider defaultStore="core">
             <store name="web_secondary" patch:after="store[@name='web']" prefix="web_secondary" getValueWithoutPrefix="true" singleInstance="true" type="Sitecore.Data.Properties.$(database)PropertyStore, Sitecore.Kernel">
                  <param ref="dataApis/dataApi[@name='$(database)']" param1="$(name)" />
                  <param resolve="true" type="Sitecore.Abstractions.BaseEventManager, Sitecore.Kernel" />
                  <param resolve="true" type="Sitecore.Abstractions.BaseCacheManager, Sitecore.Kernel" />
             </store>
         </PropertyStoreProvider>
         <databases>
         <!-- web_secondary -->
             <database id="web_secondary" patch:after="database[@id='web']" singleInstance="true" type="Sitecore.Data.DefaultDatabase, Sitecore.Kernel">
                 <param desc="name">$(id)</param>
                 <icon>Images/database_web.png</icon>
                 <securityEnabled>true</securityEnabled>
                 <dataProviders hint="list:AddDataProvider">
                     <dataProvider ref="dataProviders/main" param1="$(id)">
                         <disableGroup>publishing</disableGroup>
                         <prefetch hint="raw:AddPrefetch">
                              <sc.include file="/App_Config/Prefetch/Common.config" />
                              <sc.include file="/App_Config/Prefetch/Webdb.config" />
                         </prefetch>
                     </dataProvider>
                 </dataProviders>
                <PropertyStore ref="PropertyStoreProvider/store[@name='$(id)']" />
                    <remoteEvents.EventQueue>
                        <obj ref="eventing/eventQueueProvider/eventQueue[@name='$(id)']" />
                    </remoteEvents.EventQueue>
                    <archives hint="raw:AddArchive">
                        <archive name="archive" />
                        <archive name="recyclebin" />
                    </archives>
                    <cacheSizes hint="setting">
                         <data>100MB</data>
                         <items>50MB</items>
                         <paths>2500KB</paths>
                         <itempaths>50MB</itempaths>
                         <standardValues>2500KB</standardValues>
                    </cacheSizes>
              </database>
         </databases> 
     </sitecore>
 </configuration>

 

After applying these changes, you can see your newly created publishing target in publishing dialog in Sitecore 9:

PublishingTargets04

If you want to limit access to publishing targets for various users/roles, take a look in my other post about Setting permissions to publishing targets in Sitecore.

To conclude this post – Don’t forget that your new web database for publishing target needs to be present in SQL Server. It is not enough to have it specified in ConnectionStrings.config file!! Sitecore won’t start and will give you otherwise this nice exception:

Server Error in ‘/’ Application.

One or more exceptions occurred while processing the subscribers to the ‘property:changed’ event.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.AggregateException: One or more exceptions occurred while processing the subscribers to the ‘property:changed’ event.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[AggregateException: One or more exceptions occurred while processing the subscribers to the 'property:changed' event.]
   Sitecore.Events.EventSubscribers.RaiseEvent(String eventName, Object[] parameters, EventResult result) +1849
   Sitecore.Events.Event.RaiseEvent(String eventName, Object[] parameters) +422
   Sitecore.Data.Properties.PropertyStore.RaiseEvent(String name, Object[] parameters) +85
   Sitecore.Web.Authentication.DefaultTicketManager.IsTicketExpired(Ticket ticket, Boolean useProlongation) +357
   Sitecore.Web.Authentication.DefaultTicketManager.GetTicket(String ticketId, Boolean returnExpired) +118
   Sitecore.Web.Authentication.DefaultTicketManager.IsTicketValid(String ticketId) +49
   Sitecore.Shell.Web.ShellPage.IsLoggedIn(Boolean returnAfterLogin) +314
   Sitecore.Shell.Web.UI.SecurePage.OnLoad(EventArgs e) +22
   System.Web.UI.Control.LoadRecursive() +154
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4088

 


Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.2623.0

Happy coding 🙂