The web content management infrastructure in SharePoint 2013 includes a number of significant improvements targeted at search engine optimization for publishing sites. Major features such as cross-site publishing and managed navigation have been definitely getting a lot of attention but there are also smaller and less known features that can also be very useful.
Page SEO Properties
The Page content type in SharePoint 2013 has a number of fields dedicated to search engine optimization. You can populate these fields by selecting the Edit SEO Properties menu item in the SharePoint ribbon while editing a page.
On the Edit SEO Properties page, you can set the following field values:
Name – the page name to appear in search results. Defines the “canonical” url of the page. (Note: for term-driven pages, this maps to the Friendly Url Segment term property)
Title – the page title to appear in search results. Defines the HTML title tag value of the page. (Note: for term-driven pages, this maps to the Navigation Node Title term property)
Browser Title – if set, overrides the browser page title and HTML title tag value above.
Meta Description – short summary of page content. Search engines may display this in search results. Defines the “description” meta tag content of the page.
Meta Keywords – keywords that describe the content of the page. Defines the “keywords” meta tag content of the page.
Exclude from Internet Search Engines – indicates to search engines if this page content should be indexed or not. If the page is to be excluded, adds a noindex robots meta tag to the page.
SharePoint Cross-Site Publishing and Search Engine Optimization
The SEO Properties above work great for standard publishing pages but what if you are using cross-site publishing to display content on the publishing site? It turns out that you can also control the Browser Title, Meta Description and Meta Keywords tag content through search. The Catalog-Item Reuse web part that is typically used to display information on catalog item pages will use the following managed property values to generate meta tags for the page:
SeoBrowserTitleOWSTEXT – value will be used to populated the <title> tag
SeoKeywordsOWSTEXT – will populate the “keywords” meta tag
SeoDescriptionOWSTEXT – will set the “description” meta tag content
Basically, all you need to do is to map the crawled properties associated with your site columns to the managed properties above, run a full crawl and the meta tag will magically appear on your catalog item pages!
In order for us to be able to use different Product and ProductModel external content type fields, we need to create a number of managed properties. For this example, the following managed properties need to be created:
Navigate to Central Administration > Manage service applications > Search Service Application
Click the Search Schema link in the Queries and Results side navigation section
Click New Managed Property to create a new managed property for each of the items below
Now let’s confirm that managed navigation is enabled and configured on the SharePoint site. It is enabled for new publishing sites by default in SharePoint 2013.
Navigate to Site Settings > Look and Feel > Navigation
Make sure that Managed Navigation is selected for both Global Navigation and Current Navigation
Pages
We’ll need to create 3 new pages on the site – one top-level page listing all product models, one page that will list all products for a product model, and one page to display product details.
The first page has to be created by using the Site Actions > Add a page option so that SharePoint automatically creates and configures the navigation term.
Create a new page called Products by going to Site Actions > Add a page
Navigate to the Pages document library on the site
Create a new page called Product by using the New Document option in the ribbon
Create a new page called Product-Model by using the New Document option in the ribbon
Managed Navigation
Now is the time to configure the managed navigation to use the pages created earlier.
Navigate to Site Settings > Site Administration > Term store management
Expand the Site Collection node
Expand the Site Navigation node
Select the Products term
Select the Term-Driven Pages tab
Change target page for children of this term
Change Catalog Item Page for this category and Change Catalog Item Page for children of this category to use the Product.aspx page
Press Save to commit the changes
Add a child term to the Products navigation term for each of the product model. No settings need to be customized for the child terms.
Mountain-100
Mountain-500
Road-150
Road-450
Touring-1000
Touring-2000
The navigation term set should now looks similar to this:
Content By Search
The final steps is to add and configure content search web parts to the pages we created earlier.
Click the Products link in the global navigation to navigate to the Products.aspx page
Edit the page and add a Content Search web part from the Content Rollup category
Edit web part properties
Press Change Query to bring up the Query Builder user interface
On the Basics tab, switch to Advanced Mode, select ProductModel result source in the dropdown and clear the Query text
Press OK to close the query builder
Change the Number of items to show to 6
In the Display Templates section, select Two lines as the Item display template
In the Property Mappings section, select ProductModelSummary as Line 2
Press OK to apply changes and save the page
The Products page should now look like this:
Next, click one of the links on the page to navigate to the product model page.
Edit Product-Model.aspx page
Add a Content Search web part from the Content Rollup category
Edit web part properties
Press Change Query to bring up the Query Builder user interface
On the Basics tab, switch to Advanced Mode, select Product result source in the dropdown
Set Query text to productmodel:{Term.Name}
Press OK to close the query builder
Change the Number of items to show to 10
In the Display Templates section, select Two lines as the Item display template
Press OK to apply changes and save the page
Your Product Model page should now look similar to this screenshot:
Now follow one of the links on the page to navigate to the product detail page.
Edit Product.aspx page
Add Catalog-Item Reuse web part from the Search-Driven Content category
Edit web part properties
Press Change Query to bring up the Query Builder user interface
On the Basics tab, switch to Advanced Mode, select Product result source in the dropdown
Set Query text to productid:{URLToken.1}
Press OK to close the query builder
In the Property Mappings section, select ProductDescription managed property
SharePoint 2013 makes it very easy to index data from external systems using Business Connectivity Services (BCS) and then to surface that data in SharePoint by taking advantage of the new Content By Search web part and Managed Navigation. In this blog post you’ll find step-by-step instructions on how to create External Content Types optimized for search and index data from external systems. My next blog post will build on top of that and will show how to configure Managed Navigation and Content By Search web parts to retrieve and display the external system data on a SharePoint site.
External System
In this example I’ll be using a copy of the AdventureWorks 2012 database from Codeplex. You can download the SQL Server 2012 OLTP version of the database here: http://msftdbprodsamples.codeplex.com/
External Content Types
We’ll need to create two external content types based on the database entities – Product and ProductModel.
Launch Microsoft SharePoint Designer 2013.
Open the SharePoint site where would you like to create the External Content Types.
Select External Content Types in the left Site Objects pane and press the New External Content Type button in the ribbon.
Set the Name to Product.
Click the link next to the External System to bring up the Operation Designer.
Press Add Connection, select SQL Server and configure the Connection Properties.
In the Data Source Explorer, expand AdventureWorks2012 > Views.
Generate the New Read Item Operation and New Read List Operation for vProductAndDescription view by right-clicking it. Map the ProductID column to Identifier.
Save changes.
Navigate back to the External Content Types screen and click the Product name to bring the content type back up.
In the Fields section, select the Name field and press Set as Title in the ribbon. This will ensure that the Name field will appear as the title of the record in search results.
Save changes.
Repeat the steps above to create the ProductModel external content type. Use the vProductModelCatalogDescription view, ProductModelID as identifier and set the Name field as title.
Once all of the steps above are complete you’ll need to configure some additional settings in Central Administration. First we need to configure permissions.
Open Central Administration.
Navigate to Manage service applications and select the Business Data Connectivity Service Application then press Manage in the ribbon or simply click the service application name.
Grant your search default content access account permissions to the metadata store or individual objects by using the Set Object Permissions and Set Metadata Store Permissions in the ribbon.
Now let’s add default actions to the ProductModel and Product external content types. The default action
Click the ProductModel external content type.
Press the Add Action button in the ribbon.
Set the URL to something like http://www.contoso.com/products/{0} – this is going to be the location to the product rollup page on the publishing site.
Press Add Parameter and select the Name field.
Check the Default action checkbox and press OK.
Repeat the steps above for the Product external content type but use http://www.contoso.com/products/{0}/{1} as the url, ProductModel field as the first parameter and ProductID field as the second parameter.
Search
At this point we are almost done and are ready to crawl and index the data.
Navigate to the Search Service Application in Central Administration.
Click Content Sources link in the left navigation section under Crawling.
Click New Content Source.
Set the Name to AdventureWorks2012.
Select Line of Business Data as the Content Source Type.
Select the Business Data Connectivity Service Application in the dropdown.
Select the Crawl selected external data source option and check the checkbox next to AdventureWorks2012.
Press OK.
Start Full Crawl for the newly added AdventureWorks2012 content source.
When the crawl is done, navigate to the Search Center site and run a search query for contentsource:AdventureWorks2012. You should now be getting search results back. In my next blog post I’ll show how to surface these search results on the SharePoint site using Managed Navigation and Content By Search web parts.
Content Search web part introduced in SharePoint 2013 is a powerful tool that lets you easily retrieve and customize the appearance of search results without ever writing a single line of server-side code. In this post I’ll show how to display items from a SharePoint list in a Twitter Bootstrap Carousel on any page of your site using a Content Search web part and a custom control and item display templates.
First thing we need to do is to create a SharePoint list that will contain the items to be displayed in the carousel. Let’s start by creating the site columns below.
Navigate to Site Settings > Site columns > Create
CarouselBody site column is going to hold the text to be displayed within each carousel slide.
Name: CarouselBody
Type: Full HTML content with formatting and constraints for publishing
Group: Contoso
Require that this column contains information: Yes
CarouselImage site column will contain the image to be displayed as the slide background.
Name: CarouselImage
Type: Image with formatting and constraints for publishing
Group: Contoso
Require that this column contains information: Yes
At this point the site columns should look something like this:
Next, we need to create a content type
Navigate to Site Settings > Site content types > Create
The Carousel content type will group the site columns together
Name: Carousel
Parent Content Type: Item
Group: Contoso
Add the site columns
Add from existing site columns
Select columns from: Contoso
Columns to add: CarouselBody, CarouselImage
The content type now should look similar to this:
Now it’s time to create the SharePoint list.
Site Contents > add an app > Custom List
Name: Carousel
Enable content type management for the list.
List Settings > Advanced settings
Allow management of content types?: Yes
Add the Carousel content type to the list content types
List Settings > Content Types > Add from existing site content types
Group: Contoso
Content types to add: Carousel
Remove the default Item content type from the list
List Settings > Content Types > Item > Delete this content type
The list settings should now be as below:
Finally, we are ready to add some carousel items to the list.
Once the items are added, let’s go ahead and run a full crawl. The managed properties for each column in the list will be created automatically.
Central Administration > Application Management > Manage service applications
Search Service Application > Content Sources > Local SharePoint Sites > Start Full Crawl
When the crawl is complete we can verify that all of the information we need is in the search index by running a REST API search query.
Before we move on to the next step, we need to download the jQuery library and Twitter Bootstrap Carousel package and upload those to the Site Assets document library.
The contents of the Site Assets document gallery should look something like this:
At this point we have the content we need available and can now start developing the custom display templates. We’ll do that by copying and editing some of the standard display templates that come with SharePoint 2013 and located in the master pages gallery.
Site Settings > Master pages > Display Templates > Content Web Parts
Control_List.html > Download a Copy
Save As: Control_CarouselList.html
Replace the content of the file with the following:
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
<head>
<title>Carousel List</title>
<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:MasterPageDescription msdt:dt="string">This is a Carousel Control Display Template that will list the items.</mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106601</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#Content Web Parts;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>
<body>
<!--
Warning: Do not try to add HTML to this section. Only the contents of the first <div>
inside the <body> tag will be used while executing Display Template code. Any HTML that
you add to this section will NOT become part of your Display Template.
-->
<script>
$includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js");
$includeCSS(this.url, "~sitecollection/SiteAssets/bootstrap.min.css");
$includeScript(this.url, "~sitecollection/SiteAssets/jquery-1.8.2.min.js");
</script>
<!--
Use the div below to author your Display Template. Here are some things to keep in mind:
* Surround any JavaScript logic as shown below using a "pound underscore" (#_ ... _#) token
inside a comment.
* Use the values assigned to your variables using an "underscore pound equals"
(_#= ... =#_) token.
-->
<div id="Control_CarouselList">
<!--#_
if (!$isNull(ctx.ClientControl) &&
!$isNull(ctx.ClientControl.shouldRenderControl) &&
!ctx.ClientControl.shouldRenderControl())
{
return "";
}
ctx.ListDataJSONGroupsKey = "ResultTables";
var $noResults = Srch.ContentBySearch.getControlTemplateEncodedNoResultsMessage(ctx.ClientControl);
var noResultsClassName = "ms-srch-result-noResults";
var ListRenderRenderWrapper = function(itemRenderResult, inCtx, tpl)
{
var iStr = [];
iStr.push(itemRenderResult);
return iStr.join('');
}
ctx['ItemRenderWrapper'] = ListRenderRenderWrapper;
ctx.OnPostRender = function() {
$("div.item").first().addClass("active");
$.getScript(SP.PageContextInfo.get_siteServerRelativeUrl() + "SiteAssets/bootstrap.min.js", function() {
$(".carousel").carousel();
});
};
_#-->
<div id="myCarousel" class="carousel slide">
<div class="carousel-inner">
_#= ctx.RenderGroups(ctx) =#_
</div>
<a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a>
<a class="right carousel-control" href="#myCarousel" data-slide="next">›</a>
</div>
<!--#_
if (ctx.ClientControl.get_shouldShowNoResultMessage())
{
_#-->
<div class="_#= noResultsClassName =#_">_#= $noResults =#_</div>
<!--#_
}
_#-->
</div>
</body>
</html>
The carousel control display template is ready so we can upload it to the same location in the master pages gallery.
Site Settings > Master pages > Display Templates > Content Web Parts
Upload Document: Control_CarouselList.html
You should see the Control_CarouselList.js file automatically generated by SharePoint 2013:
The next step is to create an item display template for the carousel slides.
Similar to the control display template created earlier, we are going to copy and edit a standard item display template.
Site Settings > Master pages > Display Templates > Content Web Parts
Item_PictureOnTop.html > Download a Copy
Save As: Item_Carousel.html
Replace the file content with the following:
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882">
<head>
<title>Carousel item</title>
<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:ManagedPropertyMapping msdt:dt="string">'Image'{Image}:'CarouselImageOWSIMGE','Heading'{Heading}:'Title','Body'{Body}:'CarouselBodyOWSHTML'</mso:ManagedPropertyMapping>
<mso:MasterPageDescription msdt:dt="string">This Item Display Template will show a carousel item.</mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106603</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#Content Web Parts;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>
<body>
<!--
Warning: Do not try to add HTML to this section. Only the contents of the first <div>
inside the <body> tag will be used while executing Display Template code. Any HTML that
you add to this section will NOT become part of your Display Template.
-->
<script>
$includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js");
</script>
<!--
Use the div below to author your Display Template. Here are some things to keep in mind:
* Surround any JavaScript logic as shown below using a "pound underscore" (#_ ... _#) token
inside a comment.
* Use the values assigned to your variables using an "underscore pound equals"
(_#= ... =#_) token.
-->
<div id="Item_Carousel">
<!--#_
var carouselImage = $getItemValue(ctx, "Image");
var carouselHeading = $getItemValue(ctx, "Heading");
var carouselBody = $getItemValue(ctx, "Body");
_#-->
<div class="item">
_#= carouselImage.value =#_
<div class="carousel-caption">
<h4>_#= carouselHeading =#_</h4>
<p>_#= carouselBody =#_</p>
</div>
</div>
</div>
</body>
</html>
Upload the custom item display template to the master pages gallery.
Site Settings > Master pages > Display Templates > Content Web Parts
Upload Document: Item_Carousel.html
Verify that the associated Item_Carousel.js was successfully generated:
At last, everything is in place and we can now add a Content Search web part to the page.
Page > Edit
Insert > Web Part > Content Rollup > Content Search
Configure the web part to fetch carousel items from the search index and use the custom display templates created earlier.
Edit Web Part
Change Query
Select a query: Items matching a content type
Restrict by content type: Carousel
Display Templates
Control: Carousel List
Item: Carousel Item
Appearance
Width: 830px (set to the width of your carousel images)
Page > Save
At this point you should see the Twitter Bootstrap Carousel on the page displaying items from the Carousel SharePoint list.