Sitecore Commerce Connect – Teil 4: Preise darstellen

In den letzten beiden Teilen dieser Serie ging es um die Synchronisation von Produkten und Klassifizierungen. Das Ziel dieses Artikels ist es auch die Preise aus dem externen Shopsystem, in unserem Fall Hybris, auf der Webseite anzeigen zu können.

ProduktDemo

Der Pricing Layer ist ein “klassischer” Layer im Sitecore Commerce Connect, d.h. die Preise werden online abgerufen und nicht synchronisiert. Der Grund: Preise ändern sich häufiger und die Preisfindung ist sehr komplex, hier wird die Hoheit im externen Shopsystem (kurz ECS) belassen.

Preisabfragen

Für die Abfrage von Preisen ist der Service Provider ‚PricingServiceProvider‘ zuständig.

Eine Beispiel:

[csharp]using System.Linq;
using Sitecore.Commerce.Entities.Prices;
using Sitecore.Commerce.Services.Prices;
using Sitecore.Globalization;

namespace Comspace.Sitecore.CommerceConnect.Services.Prices
{
/// <summary>
/// Sitecore.Commerce.Prices.config
/// </summary>
public class PriceManager
{
public static Price GetPrice(string productId, Language language)
{
CustomGetProductPriceRequest request = new CustomGetProductPriceRequest(language.Name, productId);
GetProductPricesResult result = new PricingServiceProvider().GetProductPrices(request);

return result.Prices.Any() ? result.Prices.First().Value : null; //simplified
}
}
}[/csharp]

Um die Preise aus dem ECS abzurufen, muss die Pipeline ‚getProductPrices‘ der Sitecore.Commerce.Prices.config erweitert werden:

Pipeline getProductPrices

.config

[xml]<!– GET PRODUCT PRICES Gets the price object that matches the specified criteria.
This pipeline is responsible for reading pricing data from a commerce system.
This pipeline requests product pricing information from the commerce system and
then converts the output into the proper Commerce format.
–>
<commerce.prices.getProductPrices>
<processor type="Sitecore.Commerce.Pipelines.Prices.GetProductPrices.GetProductPrices, Sitecore.Commerce">
<patch:delete />
</processor>
<processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Prices.GetProductPrices, Comspace.Sitecore.CommerceConnect.Hybris" />
</commerce.prices.getProductPrices>[/xml]

Processor GetProductPrices

[csharp]using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Comspace.Sitecore.CommerceConnect.Services.Prices;
using Sitecore.Commerce.Entities.Prices;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Prices;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Prices
{
/// <summary>
/// commerce.prices.getProductPrices
/// </summary>
public class GetProductPrices : PipelineProcessor<ServicePipelineArgs>
{
public override void Process(ServicePipelineArgs args)
{
var request = args.Request as CustomGetProductPriceRequest;

//get from ECS
ExternalProduct productSource = ProductConnector.Load(request.Language, request.ProductId);
if (productSource != null && productSource.Price != null)
{
//convert to commerce connect price
Price price = new Price
{
Amount = productSource.Price.Value,
CurrencyCode = productSource.Price.CurrencyIso
};

//persist for next processor
((GetProductPricesResult) args.Result).Prices.Add("List price", price); //simplified
}
}
}
}[/csharp]

Stolpersteine

Der ‚GetProductPricesRequest‘ enthielt überraschenderweise kein Attribut für die aktuell zu synchronisierende Sprache. Daher musste dieser überschrieben werden:

[csharp]using Sitecore.Commerce.Services.Prices;

namespace Comspace.Sitecore.CommerceConnect.Services.Prices
{
/// <summary>
/// Extendended GetProductPricesRequest.
/// </summary>
public class CustomGetProductPriceRequest : GetProductPricesRequest
{
public string Language { get; set; }

public CustomGetProductPriceRequest(string language, string productId, params string[] priceTypeIds)
: base(productId, priceTypeIds)
{
Language = language;
}
}
}[/csharp]

Resumé

Zuletzt möchte ich wieder ein paar Eindrücke und Erkenntnisse zusammenfassen:

  • Der Service Layer ist eher klein und schnell erfasst.
  • Was mir wirklich gut gefällt ist, dass die Preishoheit im ECS verbleibt.
  • In umfangreicheren Produklisten sollte zwecks Performance die Nutzung der Methode/Pipeline ‚getProductBulkPrices‘ bevorzugt werden.

Wenn ihr mehr zum Sitecore Commerce Connect wissen wollt, dann schaut mal hier:

Sitecore Commerce Connect – Teil 3: Klassifizierungen synchronisieren

Im letzten Teil dieser Serie ging es um die Synchronisation von Produkten. Das Ziel dieses Blog-Artikels ist es auch Klassifizierungen unidirektional aus dem Sitecore heraus mit dem externen Commerce System (kurz ECS, in unserem Fall Hybris) zu synchronisieren und den Produkten zuzuordnen.

Klassifizierungen sind im Projekt individuell definierbare Spezifikationen zur Beschreibung von Produkten. Die sog. Classifications in Sitecore können über eine Parent-Verknüpfung (ExternalParentID) beliebig geschachtelt werden, die erste Ebene ist aber immer eine Gruppe, eine sog. ClassificationGroup.
ClassificationRepo

Synchronisation Klassifizierungen

Um Klassifizierungen zu synchronisieren muss zunächst die Pipeline ’synchronizeClassifications‘ der Sitecore.Commerce.Products.config erweitert werden:

Pipeline synchronizeClassifications

.config

[xml]
<!– SYNCHRONIZE CLASSIFICATIONS –>
<commerce.synchronizeProducts.synchronizeClassifications>
<processor type="Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.ReadSitecoreClassifications, Sitecore.Commerce">
<patch:delete />
</processor>
<processor type="Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.ResolveClassificationsChanges, Sitecore.Commerce">
<patch:delete />
</processor>
<processor type="Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.SaveClassificationsToExternalCommerceSystem, Sitecore.Commerce" >
<patch:delete />
</processor>
<processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Classifications.ReadClassifications, Comspace.Sitecore.CommerceConnect.Hybris" patch:after="processor[@type=’Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.ReadExternalCommerceSystemClassifications, Sitecore.Commerce‘]" />
<processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Classifications.ReadClassificationGroups, Comspace.Sitecore.CommerceConnect.Hybris" patch:after="processor[@type=’Sitecore.Commerce.Pipelines.Products.SynchronizeClassifications.ReadExternalCommerceSystemClassifications, Sitecore.Commerce‘]" />
</commerce.synchronizeProducts.synchronizeClassifications>
[/xml]

Processor ReadClassificationGroups

[csharp]using System.Collections.Generic;
using System.Linq;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Sitecore.Commerce.Entities.Products;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Products;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Classifications
{
/// <summary>
/// commerce.synchronizeProducts.synchronizeClassifications
/// </summary>
public class ReadClassificationGroups : PipelineProcessor<ServicePipelineArgs>
{
public override void Process(ServicePipelineArgs args)
{
var request = args.Request as SynchronizationRequest;
var groups = request.Properties["ClassificationGroups"] as List<ClassificationGroup>; //integration guide (page 9)
groups = groups ?? new List<ClassificationGroup>();

//get groups from ECS
IEnumerable<ExternalCategoryGroup> categoryGroups = ClassificationConnector.Load(request.Language);

//convert and add to commerce connect list
groups.AddRange(from @group in categoryGroups
select new ClassificationGroup
{
ExternalId = @group.Code,
Name = @group.Name
});

//persist for next processor
request.Properties["ClassificationGroups"] = groups;
}
}
}[/csharp]

Processor ReadClassifications

[csharp]using System.Collections.Generic;
using System.Collections.ObjectModel;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Sitecore.Commerce.Entities.Products;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Products;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Classifications
{
/// <summary>
/// commerce.synchronizeProducts.synchronizeClassifications
/// </summary>
public class ReadClassifications : PipelineProcessor<ServicePipelineArgs>
{
public override void Process(ServicePipelineArgs args)
{
var request = args.Request as SynchronizationRequest;
var groups = request.Properties["ClassificationGroups"] as List<ClassificationGroup>; ////integration guide (page 9)
groups = groups != null ? groups : new List<ClassificationGroup>();

foreach (ClassificationGroup group in groups)
{
var classifications = new List<Classification>();

//get categories from ECS
foreach (ExternalCategory externalCategory in ClassificationConnector.Load(group.ExternalId, request.Language)) //TBD
{
//convert to commerce connect classification
var classification = new Classification();
classification.ExternalId = externalCategory.Code;
classification.Name = externalCategory.Name;
classifications.Add(classification);

//…with sub-classifications
HandleSubCategories(externalCategory, classifications);
}
group.Classifications = new ReadOnlyCollection<Classification>(classifications);
}

//persist for next processor
request.Properties["ClassificationGroups"] = groups;
}

private static void HandleSubCategories(ExternalCategory parentCategory, List<Classification> allClassifications)
{
if (parentCategory.Categories != null)
{
foreach (var category in parentCategory.Categories)
{
var classification = new Classification();
classification.ExternalId = category.Code;
classification.Name = category.Name;
classification.ExternalParentId = parentCategory.Code;

allClassifications.Add(classification);
HandleSubCategories(category, allClassifications);
}
}
}
}
}
[/csharp]

Klassifizierungen Produkten zuordnen

Anschließend müssen die Klassifizierungen nur noch den Produkten zugeordnet werden. Und auch dafür muss wieder eine Pipeline der Sitecore.Commerce.Products.config erweitert werden:

Pipeline synchronizeProductClassifications

.config

[xml]<!– SYNCHRONIZE PRODUCT CLASSIFICATIONS
This pipeline is responsible for synchronizing and updating the references between a given product and associated classifications and categories within.
It’s assumed that classifications are already synchronized and present in CMS.
The references to categories are stored directly on the main product item. –>
<commerce.synchronizeProducts.synchronizeProductClassifications>
<processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Products.ReadProductClassifications, Comspace.Sitecore.CommerceConnect.Hybris" patch:after="processor[@type=’Sitecore.Commerce.Pipelines.Products.SynchronizeProductClassifications.ReadExternalCommerceSystemProductClassifications, Sitecore.Commerce‘]" />
</commerce.synchronizeProducts.synchronizeProductClassifications>[/xml]

Processor ReadProductClassifications

[csharp]using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Sitecore.Commerce.Entities.Products;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Products;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Products
{
/// <summary>
/// commerce.synchronizeProducts.synchronizeProductClassifications
/// </summary>
public class ReadProductClassifications : ReadProduct
{
public override void Process(ServicePipelineArgs args)
{
var request = args.Request as SynchronizeProductRequest;
var product = request.Properties["Product"] as Product;
var groups = request.Properties["ClassificationGroups"] as List<ClassificationGroup>;
groups = groups != null ? groups : new List<ClassificationGroup>();

//get product from ECS
ExternalProduct externalProduct = ProductConnector.Load(request.Language, product.ExternalId); //tbd
if (externalProduct != null && IsProductValidForImport(externalProduct))
{
//convert to commerce connect product classification groups and classifications
foreach (ExternalCategoryGroup externalCategoryGroup in externalProduct.CategoryGroups)
{
ClassificationGroup group = new ClassificationGroup();
group.ExternalId = externalCategoryGroup.Code;
group.Name = externalCategoryGroup.Name;

IEnumerable<Classification> classifications = from externalCategory in externalCategoryGroup.Categories
select new Classification
{
ExternalId = externalCategory.Code,
Name = externalCategory.Name
};
group.Classifications = new ReadOnlyCollection<Classification>(classifications.ToList());

groups.Add(group);
}
}

//persist for next processor
request.Properties["ClassificationGroups"] = groups;
}
}
}[/csharp]

Resumé

Mein erster Eindruck:

  • Es gibt viel Dokumentation, aber z.B. zum Thema Zuordnung von Klassifikationen zu Produkten konnte ich nichts finden. Da habt ihr es jetzt ja besser 😉 Häufig war dann doch dotPeek mein bester Freund.
  • Der Differenzabgleich funktionierte problemlos, Mehrsprachigkeit war im Kontext der Zuordnung von Klassifizierungen zu Produkten noch etwas holprig, da sollte ein zweiter Blick erfolgen.

Wenn ihr mehr zum Sitecore Commerce Connect wissen wollt, dann schaut mal hier:

Sitecore Commerce Connect – Teil 2: Produkte synchronisieren

Im ersten Teil dieser Serie ging es darum einen kurzen Überblick über das Sitecore Commerce Connect Modul zu verschaffen. In diesem Beitrag geht es nun um die Synchronisation von Produkten zwischen einem externen Shopsystem (kurz ECS, in unserem PoC Hybris) und Sitecore.

Zunächst ist es wichtig zu verstehen, dass Preise und Bestand im Commerce Connect nicht als Produktstammdaten gelten. Der Bestand ändert sich ständig und DEN Preis gibt es ja auch nicht, Preisfindung ist ein sehr komplexes Thema. Sitecore geht davon aus, dass diese Informationen online vom ECS ermittelt und geliefert werden. Im Teil 4 dieser Serie wird dann beschrieben, wie ihr auch an diese Informationen kommt.

image00

Die Hoheit für die Produktdaten liegt sicherlich im ECS. Für die Synchronisation der Produktdaten schlägt Sitecore folgende Varianten vor:

  1. Produkte als Items in Sitecore Datenbank (optional bidirektional)
  2. Produkte in ECS, Zugriff über Sitecore Data Provider
  3. Produkte in ECS, Zugriff über Sitecore Index

Wir haben uns im Verlauf des PoC für die Variante 1 entschieden, da diese standardmäßig vom Sitecore so vorgesehen ist und den höchsten Komfort bietet. In der Sitecore Commerce Components Overview im Kapitel “Products” sind einige Argumente für oder gegen die unterschiedlichen Variante aufgeführt.

So, jetzt aber Butter bei die Fische 🙂

Installation Modul

Falls ihr das Modul noch nicht installiert habt, findet ihr wie gewohnt eine gute Installationsanleitung auf dev.sitecore.net.

Synchronisation Produkte

Das Ziel: Titel, Beschreibung und Bilder der Produkte aus dem externen Shopsystem mit Sitecore zu synchronisieren.

image01

In folgende Pipelines der Sitecore.Commerce.Products.config muss für die unidirektionale Synchronisation der Produkte eingegriffen werden:

Pipeline getExternalCommerceSystemProductList

.config

[xml]
&lt;!– GET EXTERNAL COMMERCE SYSTEM PRODUCT LIST
This pipeline is responsible for obtaining the list of product Ids to be synchronized from the external commerce system.–&gt;
&lt;commerce.synchronizeProducts.getExternalCommerceSystemProductList&gt;
&lt;processor type="Sitecore.Commerce.Pipelines.Products.GetExternalCommerceSystemProductList.GetExternalCommerceSystemProductList, Sitecore.Commerce"&gt;
&lt;patch:delete /&gt;
&lt;/processor&gt;
&lt;processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Products.ReadProducts, Comspace.Sitecore.CommerceConnect.Hybris" /&gt;
&lt;/commerce.synchronizeProducts.getExternalCommerceSystemProductList&gt;
[/xml]

Processor ReadProducts

[csharp]
using System.Collections.Generic;
using System.Linq;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Products;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Products
{
/// &lt;summary&gt;
/// commerce.synchronizeProducts.getExternalCommerceSystemProductList
/// &lt;/summary&gt;
public class ReadProducts : PipelineProcessor&lt;ServicePipelineArgs&gt;
{
public override void Process(ServicePipelineArgs args)
{
var request = args.Request as SynchronizeProductsRequest;
var productIds = args.Request.Properties["ExternalCommerceSystemProductIds"] as List&lt;string&gt;; //integration guide (page 12)
productIds = productIds ?? new List&lt;string&gt;();

//get products from ECS
IEnumerable&lt;ExternalProduct&gt; externalProducts = ProductConnector.Load(request.Language);

//convert and add to commerce connect list
productIds.AddRange(from product in externalProducts
where product.Code != null
select product.Code);

//persist for next processor
args.Request.Properties["ExternalCommerceSystemProductIds"] = productIds;
}
}
}
[/csharp]

Pipeline synchronizeProductEntity

.config

[xml]
&lt;!– SYNCHRONIZE PRODUCT ITEM –&gt;
&lt;commerce.synchronizeProducts.synchronizeProductEntity&gt;
&lt;processor type="Sitecore.Commerce.Pipelines.Products.SynchronizeProductEntity.ReadProductFromSitecore, Sitecore.Commerce"&gt;
&lt;patch:delete /&gt;
&lt;/processor&gt;
&lt;processor type="Sitecore.Commerce.Pipelines.Products.SynchronizeProductEntity.SaveProductToExternalCommerceSystem, Sitecore.Commerce" &gt;
&lt;patch:delete /&gt;
&lt;/processor&gt;
&lt;processor type="Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Products.ReadProduct, Comspace.Sitecore.CommerceConnect.Hybris" patch:after="processor[@type=’Sitecore.Commerce.Pipelines.Products.SynchronizeProductEntity.ReadExternalCommerceSystemProduct, Sitecore.Commerce‘]" /&gt;
&lt;/commerce.synchronizeProducts.synchronizeProductEntity&gt;
[/xml]

Processor ReadProduct

[csharp]
using Comspace.Sitecore.CommerceConnect.Entities.Products;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector;
using Comspace.Sitecore.CommerceConnect.Hybris.Connector.Model;
using Sitecore.Commerce.Pipelines;
using Sitecore.Commerce.Services.Products;
using Sitecore.Diagnostics;

namespace Comspace.Sitecore.CommerceConnect.Hybris.Pipelines.Products
{
/// &lt;summary&gt;
/// commerce.synchronizeProducts.synchronizeProductEntity
/// &lt;/summary&gt;
public class ReadProduct : PipelineProcessor&lt;ServicePipelineArgs&gt;
{
public override void Process(ServicePipelineArgs args)
{
SynchronizeProductRequest syncProdRequest = args.Request as SynchronizeProductRequest;

//get product from ECS
ExternalProduct externalProduct = ProductConnector.Load(syncProdRequest.Language, syncProdRequest.ProductId); //TBD
if (externalProduct != null &amp;&amp; IsProductValidForImport(externalProduct))
{
CustomProduct product = new CustomProduct();
product.ExternalId = externalProduct.Code;
product.Name = externalProduct.Name;
product.FullDescription = externalProduct.Summary;
product.ImageUrl = HybrisSettings.Url + externalProduct.ImageUrl; //custom property

//persist for next processor
args.Request.Properties["Product"] = product; //integration guide (page 12)
}
}

protected bool IsProductValidForImport(ExternalProduct product)
{
var result = true;
if (string.IsNullOrEmpty(product.Name)) // = item.Name
{
result = false;
Log.Info("Skip product ‚" + product.Code + "‘: Name not valid.", product); //NOTE System.Messages
}
return result;
}
}
}
[/csharp]

CustomProduct

Wenn auch die Bilder synchronisiert werden sollen, muss das Produkt-Template des Commerce Connect erweitert werden. Konkret müssen dafür folgende Anpassungen vorgenommen werden:

Template
Neues Template “CustomProduct” anlegen, welches vom Standard Commerce Connect Template „Product“ erbt.

Klassen
Erweiterte Produkt-Klasse „CustomProduct“ definieren:

[csharp]
using Sitecore.Commerce.Entities.Products;
using Sitecore.Data.Items;

namespace Comspace.Sitecore.CommerceConnect.Entities.Products
{
/// &lt;summary&gt;
/// Custom product including image field.
/// &lt;/summary&gt;
public class CustomProduct : Product
{
public string ImageUrl { get; set; }

public MediaItem Image { get; set; }
}
}
[/csharp]

Die Klasse „CustomProductRepository“ definiert dann wie das erweiterte Produkt gelesen und geschrieben wird:

[csharp]
using Comspace.Sitecore.CommerceConnect.Entities.Products;
using Comspace.Sitecore.CommerceConnect.Model.sitecore.templates.User_Defined.Comspace.CommerceConnect;
using Sitecore.Commerce.Data.Products;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Product = Sitecore.Commerce.Entities.Products.Product;

namespace Comspace.Sitecore.CommerceConnect.Data.Products
{
/// &lt;summary&gt;
/// Custom product repository including image field.
/// &lt;/summary&gt;
public class CustomProductRepository : ProductRepository
{
/// &lt;summary&gt;
/// Save product data to related item.
/// &lt;/summary&gt;
/// &lt;param name="entityItem"&gt;&lt;/param&gt;
/// &lt;param name="product"&gt;&lt;/param&gt;
protected override void UpdateEntityItem(Item entityItem, Product product)
{
base.UpdateEntityItem(entityItem, product);

using (new EditContext(entityItem))
{
var url = (product as CustomProduct).ImageUrl;

var image = GetMediaItem(url, product); //TBD
ImageField imagefield = entityItem.Fields[IProductConstants.ImageFieldName];
imagefield.Alt = image.Alt;
imagefield.MediaID = image.ID;
}
}

/// &lt;summary&gt;
/// Read product data from related item.
/// &lt;/summary&gt;
/// &lt;param name="entityItem"&gt;&lt;/param&gt;
/// &lt;param name="product"&gt;&lt;/param&gt;
protected override void PopulateEntity(Item entityItem, Product product)
{
base.PopulateEntity(entityItem, product);

ImageField imageField = entityItem.Fields[IProductConstants.ImageFieldName];
(product as CustomProduct).Image = imageField == null ? null : imageField.MediaItem;
}

#region Handle MediaItem
//…
#endregion
}
}
[/csharp]

.config
Angepasste Templates und Klassen in Sitecore.Commerce.Products.config registrieren:

[xml]
&lt;!– PRODUCT REPOSITORY –&gt;
&lt;productRepository type="Sitecore.Commerce.Data.Products.ProductRepository, Sitecore.Commerce"&gt;
&lt;patch:delete /&gt;
&lt;/productRepository&gt;
&lt;productRepository type="Comspace.Sitecore.CommerceConnect.Data.Products.CustomProductRepository, Comspace.Sitecore.CommerceConnect" singleInstance="true"&gt;
&lt;template&gt;{0C589D66-A119-435A-907F-43481CD5199F}&lt;/template&gt;
&lt;branch&gt;{0C589D66-A119-435A-907F-43481CD5199F}&lt;/branch&gt;
&lt;path ref="paths/products" /&gt;
&lt;Prefix&gt;Product_&lt;/Prefix&gt;
&lt;ProductsIndex&gt;commerce_products_master_index&lt;/ProductsIndex&gt;
&lt;ManufacturerRepository ref="productManufacturerRepository" /&gt;
&lt;DivisionRepository ref="productDivisionRepository" /&gt;
&lt;TypeRepository ref="productTypeRepository" /&gt;
&lt;ClassificationsRepository ref="productClassificationsFieldRepository" /&gt;
&lt;ResourcesRepository ref="productResourcesRepository" /&gt;
&lt;RelationsRepository ref="productRelationsRepository" /&gt;
&lt;GlobalSpecificationsRepository ref="productGlobalSpecificationsRepository" /&gt;
&lt;ClassificationsSpecificationsRepository ref="productClassificationsSpecificationsRepository" /&gt;
&lt;TypeSpecificationsRepository ref="productTypeSpecificationsRepository" /&gt;
&lt;/productRepository&gt;

&lt;includeTemplates&gt;
&lt;ProductTemplateId&gt;{0C589D66-A119-435A-907F-43481CD5199F}&lt;/ProductTemplateId&gt;
&lt;/includeTemplates&gt;

&lt;!– Commerce ENTITIES
Contains all the Commerce cart entities.
The configuration can be used to substitute the default entity implementation with extended one. –&gt;
&lt;commerce.Entities&gt;
&lt;Product type="Sitecore.Commerce.Entities.Products.Product, Sitecore.Commerce" &gt;
&lt;patch:delete /&gt;
&lt;/Product&gt;
&lt;Product type="Comspace.Sitecore.CommerceConnect.Entities.Products.CustomProduct, Comspace.Sitecore.CommerceConnect" /&gt;
&lt;/commerce.Entities&gt;
[/xml]

Stolpersteine

In der Klasse „Sitecore.Commerce.Templates“ existiert eine Konstante „ProductTemplateId“, deren Id fest verdrahtet ist und nicht auf die zuvor eingerichteten Konfigurationsdateien verweist. Die Konstante wird u.a. in der Klasse „ItemClassificationService“ verwendet, daher ist dieser auszutauschen:

[xml]
&lt;itemClassificationService type="Sitecore.Commerce.Products.ItemClassificationService, Sitecore.Commerce"&gt;
&lt;patch:delete /&gt;
&lt;/itemClassificationService&gt;
&lt;itemClassificationService type="Comspace.Sitecore.CommerceConnect.Entities.ItemClassificationService, Comspace.Sitecore.CommerceConnect" /&gt;
[/xml]

Resumé

Zuletzt möchte ich ein paar erste Eindrücke und Erkenntnisse zusammenfassen:

  • Der erste Einstieg durch Pipelines in Pipelines in Pipelines ist herausfordernd.
  • Es gibt umfangreiche Dokumentationen.
  • Einige hilfreiche Klassen aus Beispielen im Internet verweisen leider auf die CommerceServer API, z.B. ProductsSearchResult und CommerceConstants. Auch in dem Dynamics AX Demoshop von Sitecore (Commerce.Dynamics.Storefront) sind Verweise auf die CommerceServer API enthalten. Die Trennung bzw. Abstraktion ist m.E. noch nicht ganz sauber erfolgt.
  • Verwunderlich fand ich zunächst, dass die Synchronisation von Bildern nicht im Standard enthalten ist. Aber dem von Sitecore definierten Prinzip “kleinster gemeinsamer Nenner” folgend, ist es verständlich, denn Bild-Quelle und -Ziel sind doch sehr projektspezifisch.
  • Der “Merchandising Manager” ist NICHT Bestandteil des Commerce Connect, sondern des CommerceServer Connect.
  • In einem echten Projekt mit einem umfangreichen Datenmodell wird der größte Aufwand in das Verständnis und das Mapping der Datenmodelle gehen.

Wenn ihr mehr zum Sitecore Commerce Connect wissen wollt, dann schaut mal hier:

Sitecore Commerce Connect – Teil 1: Ein Überblick am Beispiel Hybris

Wie in meinem Vortrag zum Thema “Evaluierung einer Hybris-Anbindung an Sitecore” auf der letzten Sitecore Usergroup in Bielefeld versprochen, möchte ich mit dieser Beitragsserie unsere ersten Eindrücke von der Anbindung eines externen Shopsystems (in diesem Beispiel Hybris) an Sitecore mittels des Commerce Connect Moduls mit euch teilen.

In diesem Artikel geht es mir darum, euch einen ersten Überblick über das Marketing-Potenzial und Funktionsumfang des Moduls zu verschaffen. In den nächsten Beträgen wird es dann technischer mit konkreten Ausschnitten aus Konfigurationsdateien und Quellcode.

Warum sollten WebCMS und E-Commerce Platform verbunden werden?

Bevor wir an die technischen Details gehen, erlaube ich mir zunächst einige Gedanken aus Sicht von Produkt-Management, Marketing und Vertrieb auf Betreiberseite:

Webnutzer erwarten immer mehr eine einheitliche User-Experience, die sich über alle Kanäle und Plattformen eines Unternehmens erstrecken soll. Zudem  bringen auch Online-Shop Systeme kleinere CMS-Funktionalitäten mit und damit wird auch die Darstellung von Inhalten immer besser. Warum sollten dann CMS und Shop miteinander verbunden werden?

Sitecore bietet bereits in seiner eigenen Suite ein umfangreiches Bundle an Funktionen, um verschiedenste Touchpoints (Webseite, Newsletter, Social Media, Offline-Kanäle am POS usw.) zu einem Nutzererlebnis aus einem Guss zu verschmelzen.

Mit diesem Beispiel möchte ich Möglichkeiten aufzeigen, mit denen Besuchern auch auf Unternehmenswebseiten die Kernfunktionalitäten eines Online-Shops angeboten werden können (wie bspw. Produkte in den Warenkorb legen) und wie diese kombinierten Webseiten- und E-Commerce-Daten dann von der Unternehmenswebseite automatisch an das Shopsystem übergeben werden.

Ein Beispiel für eine Customer Journey mit Optimierungspotenzial sähe beispielsweise so aus:

Der Kunde schaut auf einer Webseite nach einem Produkt, muss sich das Produkt merken und im separaten Online-Shop danach suchen um zu bestellen. 

Das bedeutet:
Durch die zwei separaten Technologien Webseite und Shop entsteht für den Kunden Fehler- und Frustrations-Potenzial. Für Unternehmen und Shop-Anbieter kann das bedeuten: Erhöhte Abbruchgefahr und damit niedrigere Conversion-Rate.

Mit Lösungen wie dem Commerce Connect arbeitet die Technologie im Hintergrund für den Kunden, nimmt ihm Arbeitsschritte ab und erhöht damit die Wahrscheinlichkeit, dass es zu einem Verkauf kommt.

Der Endkunde bemerkt so den Technologiewechsel aus dem WebCMS in den Online-Shop überhaupt nicht und hat ein nahtloses Nutzererlebnis im Bestellprozess.

Kurzvorstellung Sitecore Commerce Connect

Sitecore Commerce Connect sieht sich als Framework und API zur nahtlosen Integration von 3rd-Party Commerce Systemen in Sitecore. Das Ziel ist die Überführung der Experience Marketing Features in die Commerce Welt:

  • Einheitliche Darstellung:  Produktkataloge, “normale” Inhalte und Bilder aus einem Guss
  • Bearbeitung von Produktkatalogen, Seiteninhalten und Bildern in einen System
  • Nutzung der Sitecore Facettensuche über ALLE Inhalte.
  • Personalisierung auch über das Kaufverhalten der Besucher
  • Tracking von Conversions und Values rund um den Einkauf
  • Identifizierung von und Einblick in die wertvollsten Kunden
  • Reaktion auf Änderungen im Geschäft, in Echtzeit

Konkreter Umfang des Commerce Connect Moduls

Das Sitecore Modul bietet die Möglichkeit Produktkataloge mit dem externen Commerce System zu synchronisieren, d.h. es stellt entsprechende Templates, Klassen, Repositories, Import-Pipelines etc. zur Verfügung:

Sitecore-Commerce-Connect-Modul

Erste Engagement-Pläne zu Warenkorb-Abbrüchen, neuen Aufträgen und Wiederverfügbarkeit von Produktbeständen werden mitgeliefert und genutzt:

Sitecore-Commerce-Connect-Engagement-Plan

Selbstverständlich kommen auch Erweiterungen für die Sitecore Rule Engine mit:

Sitecore-Commerce-Connect-Rule-Engine

Das Framework des Sitecore Commerce Connect 

Die Architektur wird von Sitecore wie folgt skizziert, wobei der Commerce Server Connector und der Dynamics AX Connector fertige Connectoren von Sitecore selbst sind und der Hybris Connector von uns im Rahmen der Evaluierung entwickelt wurde.

Service Layer:

Folgende Bereiche deckt das Modul ab:

  • Warenkorb
  • Preise
  • Kunden und Benutzer
  • Bestände
  • Produkte
  • Aufträge
  • Geschenkkarten
  • Wunschlisten
  • Bezahlung
  • Versand
  • Treueprogramme

Die einzelnen Layer sind optional und unabhängig voneinander. Ein Layer umfasst ein Datenmodell und Pipelines mit ggf. zugehörigen Service Providern. Die farblich markierten Service Layer wurden im Rahmen des PoC näher beleuchtet. Wenn ihr einen Eindruck haben möchtet was sich dahinter verbirgt, habt etwas Geduld – die zugehörigen Artikel folgen.

Prinzipien

Weil sie mir so gut gefallen haben, hier eine kurze Zusammenfassung und Übersetzung der Prinzipien welche dem Modul von Sitecore selbst auferlegt wurden:

  • Simplicity – kleinster gemeinsamer Nenner
  • Extensibility – Domain Model erweiterbar
  • Independently – keine Abhängigkeit zwischen Service Layern
  • Abstraction – keine Sitecore oder Shopsystem Abhängigkeit in Service Layern
  • Pipelines – jeder Service Layer benutzt Sitecore Pipelines
  • Fallback – fehlende Implementierungen im Shopsystem können überbrückt werden

Erstes Resumé

Mein Eindruck nach der Evaluierung des Commerce Connect anhand einer Hybris-Anbindung:

  • Der erste Einstieg ist herausfordernd, kurz stand ich davor wie “der Ochs vorm Berg”. Auf dem Partnertag in Frankfurt wurde von Sitecore eine Schulung zu dem Modul angekündigt. Die kann ich dann nur empfehlen.
  • Das bringt mich zu den zur Verfügung stehenden Materialien:
    • Es gibt umfangreiche Dokumentationen über das Modul im Developer Netzwerk.
    • Cookbooks gibt es leider keine, diese helfen sonst häufig die erste Hürde zu nehmen.
    • Wenn die Dokumentation nicht weiter hilft, gibt es im Internet aktuell leider noch wenig Material zum Commerce Connect.
    • Geholfen haben immer wieder die herunterladbaren Beispiel-Implementierungen für AX und CommerceServer und natürlich dotPeek.
  • Customizing gehört zum Grundkonzept. Durch eine gute Abstraktion ist fast alles flexibel anpassbar. Das gefällt, auch wenn es manchmal nicht einfach ist, im Pipeline-Dschungel den Überblick zu bewahren.
  • Für eine solide und benutzerfreundliche Integration ist eCommerce-KnowHow unumgänglich. Die dahinterliegenden Modelle und Prozesse müssen durchdrungen werden.
  • Die Komplexität einer Commerce Integration bringt auch höhere Konzeptions- und Abstimmungsaufwände mit sich als vielleicht sonst im CMS-Umfeld üblich.
  • Das Modul umfasst keine Layout-Komponenten und keine speziellen Applikationen.
  • Der “Merchandising Manager” ist  NICHT Bestandteil des Commerce Connect, sondern des CommerceServer Connect.
  • Eine gute Einsatzmöglichkeit für das Modul ist m.E. eine PIM-Integration.
  • Zu guter Letzt: Die Arbeit mit dem Modul hat mir Spaß gemacht!

Die Präsentation zum Vortrag:

In den kommenden Tagen werde ich diese Serie mit den folgenden Artikeln fortführen:

 

 

Schnelleinstieg in das Team Development for Sitecore (TDS)

Test TDS

Ihr habt noch nicht mit dem TDS gearbeitet, möchtet es aber mal ausprobieren? Dann seid ihr hier richtig. Mit diesem Blog-Beitrag möchte ich euch einen schnellen Einstieg in das TDS vermitteln. Wenn ihr wissen wollt was das TDS ist und wie es grundsätzlich funktioniert, dann könnt ihr das in diesem Beitrag nachlesen.

Installation des TDS

Auf der Webseite von Hedgehog könnt ihr das TDS herunterladen und 30 Tage lang kostenlos testen. Anschließend müsst ihr euch nur noch den zu eurem Visual Studio passenden Windows Installer heraussuchen, z.B. den HedgehogDevelopmentTDS_VS2013.msi und euch durch den Assistenten klicken.

Konfiguration von TDS Projekten

Zunächst setzt ihr wie gewohnt ein neues Projekt auf, d.h. ihr installiert Sitecore und richtet eine Visual Studio Projektmappe/ Solution ein.

Anschließend werden die TDS-Projekte eingerichtet. Eine erste TDS-Projektstruktur könnte wie folgt aussehen:

  • Tds.Core – enthält Client-Anpassungen
  • Tds.Master.Templates – enthält Templates
  • Tds.Master.Layouts – enthält Layouts, Sublayouts etc.
  • Tds.Master.Content – Beispielcontent, den jeder Entwickler braucht.

Je Projekt führt ihr folgende Schritte durch, wie hier am Beispiel des Tds.Master.Template-Projektes visualisiert:

1. TDS-Projekt anlegen

Rechtsklick auf der Projektmappe > Hinzufügen > Neues Projekt:

TDS Project

2. TDS-Projekt konfigurieren

Rechtsklick auf dem TDS-Projekt > Eigenschaften:

General Tab

  • Datenbank eintragen, hier “master”
  • Hinweis: Ein Projekt, z.B. das Tds.Master.Template-Projekt sollte mit dem Web-Projekt verbunden werden, dann wird das Web-Projekt auch automatisch mit deployed (Pfad siehe Build Tab).

General Tab TDS

Build Tab

  • Sitecore Web Url: Url unter der das Projekt zu erreichen ist
  • Sitecore Deploy Folder: Root-Verzeichnis der Webseite
  • Den Sitecore Connector installieren und die Verbindung testen.
  • Hinweis: Die erste generierte Guid in ALLE Projekte kopieren, diese muss innerhalb der Projektmappe identisch sein.

Test TDS

3. Item Synchronisation einrichten

Um die zu synchronisierenden Items einzurichten, klickt ihr mit der rechten Maustaste auf TDS-Projekt > “Get Sitecore Items” und wählt die Items aus:

Get Sitecore Items TDS

Anschließend könnt ihr einfach mal ein Item in Sitecore anlegen und im Visual Studio das TDS-Projekt mit der rechten Maustaste > “Sync with Sitecore” synchronisieren:

Sync TDS

Das war’s schon. Das erste TDS-Projekt ist fertig eingerichtet.

Einrichtung Code Generierung

Als nächsten Schritt möchte ich mit euch noch die automatische Generierung von Template-Klassen mittels Glass.Mapper einrichten.

1. Installation Glass.Mapper.Sc

Bevor wir damit starten, solltet ihr sicher stellen, dass im Web-Projekt

  • das NuGet-Paket “Microsoft ASP.NET MVC” installiert ist und
  • die Sitecore.Kernel-Bibliothek als Verweis zur Verfügung steht.

Anschließend müsst ihr einfach das NuGet-Paket “Glass.Mapper.Sc“ von nuget.org installieren:

Glass.Mapper.Sc TDS

2. Generierung einrichten

Hierzu bedarf es folgender Schritte:

  • In den Projekteigenschaften des TDS-Projekts, das die Templates synchronisiert (hier Tds.Master.Template), auf dem Tab “Code Generation” die Code Generierung aktivieren.
  • T4-Templates für den Glass.Mapper hier herunterladen.
  • Folgende tt-Dateien im Tds.Master.Templates Projekt im Folder “Code Generation Templates” ablegen und zum TDS-Projekt hinzufügen:
    • Helpers.tt
    • GlassV3Header.tt
    • GlassV3Item.tt
    • GeneralExtensions.tt
    • Inflector.tt
    • StringExtensions.ttt
  • Die Generierung konfigurieren
    • Target Project:  Web-Projekt
    • Code Generation Target File:  z.B. “Model/GeneratedClasses.cs”
    • Base Namespace: z.B. Modle
    • Header Transformation File: GlassV3Header.tt
    • Base Project Transformation File: GlassV3Item.tt

Generation TDS

3. Generierung testen

Entweder ihr klickt mit der rechten Maustaste auf das TDS-Projekt > “Re-Generate Code for all Items” oder ihr fügt im Sitecore ein neues Item hinzu und synchronisiert dieses mit dem TDS-Projekt.

Wenn ihr keine Fehlermeldung erhaltet, dann findet ihr eure Templates als Klassen in der “GeneratedClasses.cs” wieder. Andernfalls schaut mal im nächsten Absatz.

Mögliche Stolpersteine

Fehlender Namspace Glass.Mapper.Sc.Mvc

Es ist wichtig, dass ihr erst ASP.NET MVC installiert und dann das Glass.Mapper.Sc-Paket, andernfalls wird der Verweis auf “Glass.Mapper.Sc.Mvc” nicht mit installiert.

T4-Templates gesperrt

Wenn ihr die Meldung ”ErrorGeneratingOutput” wiederholt in der generierten Klasse findet, dann liegt es häufig daran, dass ihr die T4-Templates von einer externen Quelle geladen habt und diese noch entsperrt werden müssen:

Stolpersteine TDS

Überflüssige Leerzeile

Wenn ihr in der generierten Klasse untenstehende Meldung seht, dann schaut mal im “GlassV3Item.tt”. Dort ist vermutlich in der letzten Zeile eine Leerzeile, die zu entfernen ist.

*********************************************
 An error occured while generating code for item '/sitecore/templates'.
T4 Template: F:\SitecoreDEV\Projekte\TdsDemo\TdsDemo.Tds.Master\Code Generation Templates\glassv3item.tt
Errors:
Kompilierte Transformation: Ungültiges Token 'this' in Klasse, Struktur oder Schnittstellenmemberdeklaration.
Kompilierte Transformation: Die Methode muss einen Rückgabetyp besitzen.
Kompilierte Transformation: Typ erwartet.
*********************************************

Wie geht es weiter?

Die erste Einrichtung habt ihr jetzt hinter euch und damit habt ihr auch einen ersten Eindruck vom TDS gewonnen. Wenn ihr das Thema vertiefen wollt, empfehle ich euch z.B. das Manual von Hedgehog. Zum Thema automatische Builds und Deployment-Strategien findet ihr im Build Extensions Whitepaper Ansätze.

Ich freue mich über Kommentare zu euren Erfahrungen mit dem TDS!

Sitecore Usergroup Deutschland – Entstehung, Ziele und Entwicklung

Workshop Kreativität

Was ist eine Usergroup?

Usergroups finden sich überwiegend im IT-Umfeld und verstehen sich als Anwendergruppen für eine bestimmte Software oder Technik. Die Mitglieder einer Usergroup sind bestrebt, die Software gemeinsam weiter zu entwickeln, ihre Interessen gegenüber der Herstellerfirma zu vertreten und einen regelmäßigen Erfahrungsaustausch zu pflegen.

Im Bereich der Content Management Systeme bestehen einige Usergroups bereits seit längerem, so z.B. die OpenText Usergroup und die OpenCMS Usergroup.

Von der Idee zum 1. SUG-Treffen

Sitecore Usergroup Deutschland LogoSitecore Usergroups wurden bereits bspw. in der Schweiz, den Niederlanden und den USA gegründet. Da das Sitecore CMS immer stärker auch bei Web-Projekten für den deutschen Markt eingesetzt wird, hat sich Christopher Wojciech von der netzkern AG zum Ziel gesetzt diese Community ebenfalls auch im deutschen Raum aufzubauen. Nachdem das erste Treffen in Köln ein voller Erfolg war, wollte man dies wiederholen. Aufgrund des Besuchs von webit! Gründer Sven Haubold in Köln hat man sich dazu entschlossen das nächste Treffen in Dresden zu veranstalten. Ein ebenso großes Engagement zeigte comspace aus Bielefeld und somit hat sich eine kleine Gruppe aus sehr motivierten Menschen gefunden, um die Sitecore Communtiy in Deutschland weiter nach vorne zu bringen.

Workshop Kreativität

 

Zielsetzung und Zielgruppen der Sitecore Usergroup

Da das Sitecore CMS in Deutschland einerseits noch nicht so lange auf dem Markt ist wie andere CMS-Lösungen, andererseits aber enormes Potential für digitale Marketingprojekte bietet und sich schnell weiter entwickelt, stehen der Erfahrungsaustausch und die gezielte Verbreitung von neuen Lösungen im Sitecore-Umfeld im Vordergrund.

Zu diesem Zweck wurden gemeinsam organisierte und regelmäßig stattfindende Veranstaltungen geplant, die Sitecore-Entwickler und -Anwender sowie Marketing- und IT-Verantwortliche zusammen bringen – sprich potentiell jeden, der in seinem Arbeitsalltag mit Sitecore zu tun hat, ob auf Agentur- oder Kundenseite. Diese Treffen dienen dem Wissensaustausch und der Weiterbildung, u.a. durch Fachvorträge, in denen über neue Lösungsansätze, Tools und Einsatzszenarios in der Praxis berichtet werden.

Auch außerhalb der Veranstaltungen soll ein fachlicher Austausch zu Erfahrungen, Ideen und auch Problemen mit dem Sitecore CMS nicht zu kurz kommen. Dazu dient z.Zt. eine Sitecore Usergroup Deutschland XING-Gruppe. Für die Zukunft ist eine Community geplant, die allen Sitecore Usergroup-Interessierten – unabhängig von einer XING-Mitgliedschaft – offen steht.

Nicht zuletzt bildet die Sitecore Usergroup eine gemeinsame Interessenvertretung von Anwendern und Partnern gegenüber Sitecore als Hersteller. Durch einen regelmäßigen Dialog mit Sitecore möchten wir die Wünsche und Anregungen der deutschen Anwender gesammelt und strukturiert kommunizieren.

Was die Usergroup nicht ist

Wichtig für die Organisatoren war es auch sich auf gewisse Rahmenbedingungen zu einigen. Dazu gehörte es festzulegen welche Zwecke die Sitecore Usergroup nicht verfolgt:

  •         Die Usergroup ist nicht der Platz für Kundengespräche.
  •         Die Usergroup dient nicht der Kundenakquise.
  •         Die Usergroup-Treffen sind keine Werbeveranstaltung.

Erfahrungen aus den ersten Sitecore Usergroup Treffen

Mittlerweile haben die ersten Sitecore Usergroup Treffen stattgefunden – im Herbst 2014 in Köln und im Frühjahr 2015 in Dresden. Die Events mit Vorträgen von Sitecore-Kollegen, – Partnern und -Kunden und mit einem kulturellen Rahmenprogramm wurden von allen Zielgruppen gut angenommen, auch wenn Entwickler von Sitecore-Partneragenturen in der Überzahl waren. Präsentiert wurden sowohl technische als auch Consulting-Themen oder Kundenprojekte, bspw. “Sitecore Health – Monitoring und Stabilität von Sitecore Umgebungen”, “Vernetzt ans Ziel – die neue Website der Dresdner Verkehrsbetriebe AG” oder Mehrwert für Webprojekte mit Sitecore und Microsoft Azure.

Wie geht es weiter?

Wir haben große und spannende Pläne um diese Community weiter zu vergrößern. Wir wollen eine kontinuierliche Plattform schaffen und dies auch in der Außenwirkung bekräftigen. Seid gespannt und kommt zum nächsten Treffen, dann erfahrt ihr mehr!

Daher lade ich Euch zu guter Letzt…

… herzlich zum 3. Sitecore Usergroup Treffen am 30. September 2015 im Historischen Museum in Bielefeld ein. Diese spannenden Themen stehen auf dem Programm:

  •         Evaluierung einer Hybris-Anbindung an Sitecore mittels Commerce Connect
  •         The good, the bad and the ugly Sitecore module
  •         Auf dem Weg zur Connected Customer Experience – Möglichkeiten zu omni-channel Strategien mit Sitecore

Ausführlichere Informationen zum Programm und die Möglichkeit zur Anmeldung finden Sie hier.

Professionelle Sitecore Entwicklung mit dem TDS

Sitecore-Versionskontrollsystem

Wofür steht eigentlich TDS?

TDS steht für Team Development for Sitecore. Es ist im Wesentlichen eine Visual Studio Erweiterung der Firma Hedgehog, einem Technologie-Partner von Sitecore mit Sitz in den USA.

Was macht das TDS?

Zusammengefasst ermöglicht bzw. reduziert es die Komplexität von:

  • Automatisierten Builds und Deployments in Sitecore
  • Autarken, schnell aufsetzbaren Entwicklungsumgebungen
  • Generierung von Template-Klassen

Im Detail bedeutet das Folgendes:

Item Synchronisation

Sitecore Entwicklung heißt vereinfacht, Quellcode im Visual Studio zu schreiben und Templates, Layouts, Client-Erweiterungen etc. als Items über Sitecore in der Datenbank anzulegen und zu bearbeiten. Der Quellcode wird selbstverständlich in einem Versionskontrollsystem, wie z.B. SVN oder Git, verwaltet, aber was passiert mit den Anpassungen in der Datenbank?

Da die Sitecore Items nicht im Versionskontrollsystem liegen, ist kein ganzheitlicher Stand im Nachhinein einsehbar, geschweige denn bearbeitbar.

Das TDS schließt diese Lücke in der Sitecore Entwicklung: es bietet eine komfortable Möglichkeit auch Sitecore Items mittels Versionskontrollsystem zu verwalten. Dialoggesteuert können Items aus der Versionsverwaltung in das Sitecore eingespielt werden oder aus dem Sitecore zur Ablage in selbiger serialisiert werden.

Sitecore Versionskontrollsystem
TDS Item Synchronisation

Durch die ganzheitliche Betrachtung von Quellcode und Datenbank, können wir in der Entwicklung die Vorteile eines Versionskontrollsystems voll nutzen:

  • Es kann in Branches entwickelt werden, die dann zu definierten Zeitpunkten zu Releases zusammengeführt werden.
  • Definierte Stände können jederzeit vollständig wiederhergestellt werden.
  • Wir können sinnvoll (ohne Sitecore Packages) mit verteilten Entwicklungsdatenbanken arbeiten: Jeder Entwickler hat seine eigene Datenbank statt der bisher globalen Datenbank.
  • Jeder Entwickler kann einfach mal einen Branch auschecken, etwas ausprobieren inkl. Datenbankanpassungen und hinterher einfach wieder alles verwerfen.

Automatisches Deployment

Mittels TDS können Sitecore Update-Packages gebaut werden, die dann im Rahmen eines automatischen Deployments auf einem Zielsystem ausgeliefert werden können.

Das Update-Package kann einfach mittels Sitecore Installation Wizard (zu finden unter /sitecore/admin/UpdateInstallationWizard.aspx) auf dem Zielsystem installiert werden. Für eine automatisierte Auslieferung steht  z.B. das Modul Sitecore.Ship zur Verfügung, mit dem die Datei mittels HTTP-Request hochgeladen werden kann.

Achtung: Nicht einfach das Sitecore.Ship vom NuGet-Server installieren, denn dieses ist nicht Sitecore 8 kompatibel. Bitte in diesen Fällen die Version von GitHub nutzen.

Generierung von Template-Klassen

Das TDS bietet außerdem die Möglichkeit, Template-Klassen basierend auf T4-Templates zu generieren. Entsprechende Glass.Mapper-Templates findet ihr auf GitHub. Der Glass.Mapper ist ein OR-Mapper für Sitecore Items, Details findet ihr hier.

Die Template-Klassen werden vom TDS während der Item-Synchronisation im Hintergrund automatisch mit aktualisiert.

Zu guter Letzt sei hier noch gesagt, dass auch ein einfaches Klassen-Template Diagramm generiert werden kann:

Sitecore Klassen-Template-Diagramm
TDS Template-Klassen-Diagramm

Gibt es Alternativen?

Natürlich ist das TDS kein Muss. Es gibt auch kostenfreie Tools, die das TDS teilweise ersetzen. Im Folgenden findet ihr eine Liste der Module, welche zusammen beispielsweise die Funktionen alternativ übernehmen können:

Alle verwendeten Module sind SharedSource und stehen auch auf GitHub zur Verfügung.

Mir hat die Alternativ-Idee grundsätzlich gut gefallen, denn TDS ist ja auch nicht gerade günstig. Aufgrund folgender Punkte haben wir uns dennoch für das TDS entschieden:

  • Nicht alle Module waren zum Testzeitpunkt Sitecore 8-kompatibel.
  • Anpassungen sind zwar möglich, aber wären dann auch dauerhaft erforderlich. Eine neue Sitecore Version heißt Test und ggf. neues Build.
  • Komfort und Stabilität: Für vergleichbare Funktionen sind mehr bzw. umständlichere Schritte erforderlich und das führt letztlich immer zu Reibungsverlusten.
  • Wir fokussieren uns auf unser Business CMS-Entwicklung und kaufen uns die erforderlichen Entwicklungswerkzeuge, samt Support und Wartung.

Erste Schritte

Neugierig geworden? Dann schaut mal auf der Webseite von Hedgehog: 30 Tage könnt ihr das TDS kostenlos evaluieren.

Und für den Schnelleinstieg steht euch hier im Blog eine Schritt für Schritt Anleitung zur Verfügung

Fazit

Als Sitecore-Entwicklerin möchte ich ohne das TDS nicht mehr arbeiten.

In wenigen Minuten ist ein neuer Branch eines Kundenprojektes zur Entwicklung auf meinem Rechner bereit:

  1. Branch des Kundenprojektes erstellen und ausschecken
  2. Leere Sitecore Installation in der erforderlichen Sitecore Version mittels SIM Tool installieren
  3. Visual Studio Solution des Projektes öffnen
    1. Item Synchronisation des TDS ausführen
    2. Solution veröffentlichen.
  4. Site in Sitecore publizieren.

Und dass ich keine Deployments mehr manuell mittels Packages, sondern automatisiert mittels TDS und Buildserver durchführen möchte, versteht sich wohl von selbst 🙂

Welche Erfahrungen habt ihr mit dem TDS gemacht? Ich freue mich auf Eure Kommentare.

Learnings und Tipps aus dem Upgrade von Sitecore 7.5 auf Sitecore 8.0

Sitecore Update-Installation-Wizard

Unser erstes Projekt-Upgrade von Sitecore 7.5 auf Sitecore 8.0 ist abgeschlossen und wir wollen es nicht versäumen, unsere Erfahrungen aus diesem Prozess mit Ihnen zu teilen. Als Ausgangsbasis für den Upgrade Prozess dient wie bei allen Sitecore Upgrades der „Sitecore Upgrade Guide“.

Dieser Guide bietet eine gut nachzuvollziehende Schritt-für-Schritt-Anleitung

Im wesentlichen besteht dieser Prozess aus den folgenden Schritten:

  1. Backup von Website und Datenbanken
  2. Ausführung von SQL Server Update Skripten auf den Sitecore Datenbanken
  3. Installation des Upgrade Packages über den “Update Installation Wizard”
  4. Aktualisierung der Konfigurationsdateien
  5. Neuaufbau der Suchindizes und der Link Datenbank
  6. Ggf. Aktualisierung weiterer Module (z.B. “Web Forms For Marketers”-Modul)
Sitecore Update-Installation-Wizard
Sitecore Update-Installation-Wizard

Nach dem Upgrade-Prozess sahen wir uns mit einigen Problemen konfrontiert. Dazu gehörten sowohl Issues im Sitecore Client als auch die Aggregation der Analytics-Daten in die Reporting Datenbank.

Probleme und Lösungen beim Laden des Sitecore Clients

1. Fehlermeldung „Could not load type ‚Sitecore.Shell.Applications.WebEdit.Commands.WebEditCommand‘ from assembly ‚Sitecore.Client, Version=7.0.0.0, Culture=neutral, PublicKeyToken=null‘.“

Hintergrund ist die Einführung der neuen “Sitecore.ExperienceEditor”-Assembly. Wir verwenden eine Reihe von Custom Buttons im Page Editor. Diese hingen vorher vom “Sitecore.Shell.Applications.WebEdit.Commands”-Namespace ab. Dessen Funktionen sind mit Sitecore 8 nun in die neue Assembly “Sitecore.ExperienceEditor.dll” ausgelagert worden.Die Lösung bestand darin, in der Visual Studio Solution einen Verweis zu dieser neuen Assembly hinzuzufügen und das Projekt neu zu bauen.

2. Fehlermeldung „Could not resolve type name: Sitecore.ContentSearch.Events.PublishingEventHandler, Sitecore.ContentSearch (method: Sitecore.Configuration.Factory.CreateType(XmlNode configNode, String[] parameters, Boolean assert)).“

Durch den Austausch der Sitecore.ContentSearch gegen die Default Sitecore 8 „Sitecore.ContentSearch.config“ bzw. „Sitecore.ContentSearch.dll“ konnte dieses Problem schnell ausgeräumt werden.

3. jQuery Konflikt mit Prototype im Sitecore 8 Experience Editor

JavaScript-Konflikte traten durch den parallelen Einsatz der JS-Frameworks Prototype und jQuery zu Tage. Mittels Wrapper-Workaround konnte dieses Problem umgangen werden.

Probleme und Lösungen bei der Aggregation der Analytics-Daten in die Reporting-Datenbank

1. Leere „Segments“- und „TreeDefinition“-Tabellen in der Reporting-Datenbank.

Als Workaround wurden die betreffenden Tabellen mit einer “sauberen” Default Sitecore 8.0 Reporting Datenbank manuell abgeglichen und ergänzt.

2. Fehlermeldung „Exception: System.IO.FileFormatException
An error occurred while deserializing the Pages property of class Sitecore.Analytics.Model.VisitData: An error occurred while deserializing the PageEvents property of class Sitecore.Analytics.Model.PageData: An error occurred while deserializing the CustomValues property of class Sitecore.Analytics.Model.Entity: Die“ Zeichenfolge kann keine Länge von 0 (nu ll) haben.““

Diese Exceptions sind der Tatsache geschuldet, dass das WFFM 2.5 Modul in Sitecore 7.5  Ereignisdaten in der Analytics MongoDB in anderer Weise abbildet und speichert als mit WFFM 8.0. Zudem werden unterschiedliche Klassen zur Deserialisierung während der Aggregation verwendet.Eine Lösung konnte dank des Sitecore-Supports umgesetzt werden: Dieser lieferte entsprechende Patches zur Aggregation historischer WFFM-Analytics-Daten.

Weitere Tipps für eine reibungslose Aktualisierung von Sitecore 7.5 auf 8.0

Folgende Punkte halten wir generell aus unseren Erfahrungen mit dem Upgrade auf Sitecore 8.0 für erwähnenswert:

1. Besondere Aufmerksamkeit sollte auf die Aggregation der Analytics-Daten und zusätzlicher Module wie WFFM oder EXM gelegt werden. Falls diese Anwendungen gar nicht erst eingesetzt werden sollen, sollte das Upgrade kaum Probleme bereiten.

2. Custom Buttons im Experience Editor können übergangsweise zunächst auf die alte SheerUI umgestellt und dann ggf. in das neue SPEAK-Framework umprogrammiert werden. Hilfreiche Hinweise zu diesem Thema liefert der Artikel “A New Look to Buttons in Experience Editor”.

3. Eine Übersicht über bereits bekannte Bugs in Sitecore 8 liefert die Sitecore Knowledge Base-Seite.

Welche Erfahrungen haben Sie mit einem Upgrade auf Sitecore 8.0 gemacht und welche Tipps können Sie anderen Sitecore-Entwicklern geben?

Wir freuen uns auf Ihre Kommentare.

Automatische Personalisierung von Webseiten oder: BENUTZ HAMSTER MIT MIKROWELLE

Maniac Mansion Screenshot (tentakelvilla.de)

Eine Frau kam eines Tages zu Gandhi und sagte: „Gandhi, bitte sage meinem Sohn, er soll keinen Zucker mehr essen!“ – Gandhi sah die Frau und ihren kleinen Sohn kurz an und meinte dann: „Komm in 2 Wochen wieder“. Die Frau war enttäuscht, denn die Reise war lang und sehr hart gewesen. Diese in 2 Wochen noch einmal anzutreten würde sie sehr viel Kraft und Geld kosten. Aber sie tat es.

Nachdem zwei Wochen vergangen waren stand sie wieder vor Gandhi. Der beugte sich zum kleinen Sohn herunter und sagte: „Junge, iss keinen Zucker mehr.“

Die Frau wurde böse: „DAFÜR sollte ich nun die gleiche Reise nach zwei Wochen noch einmal machen? Warum konntest Du das nicht schon beim letzten Mal sagen?“ Und Gandhi sagte: „Erst musste ich doch selber aufhören Zucker zu essen.“

Was hat Gandhi mit automatisch personalisierten Webseiten zu tun?

Ein ganz, ganz wichtiger Punkt um das Potenzial von personalisierten Webseiten voll auszuschöpfen ist es, dass Sie sich in Ihre Besucher hineinversetzen und mit deren Augen sehen. So wie Gandhi sich zunächst selber das Zuckeressen abgewöhnen musste, um darüber mit dem kleinen Jungen zu sprechen.

Was sie in diesem recht langen Artikel, der die schriftliche Version eines Vortrags auf der dmexco 2014 ist, noch erfahren werden, habe ich Ihnen hier einmal zusammen gefasst:

  • Gleichen Sie Ihr Angebot mit dem Bedarf des Kunden ab
  • Sehen Sie das Verhalten des Nutzers vorher
  • Planen Sie Klickverläufe

tl;dr: Durchlaufen Sie verschiedene Wege, die Ihre verschiedenen Benutzer durch Ihre Webseiten führen. Testen Sie verschiedene Klickpfade und Konversionsziele. Wird der Bedarf der Besucher gedeckt und die Erwartungen erfüllt? In diesem Artikel finden Sie einige einfache Beispiele und Werkzeuge, wie Sie das Potenzial für Personalisierung in Ihren Webseiten evaluieren und Nutzerverhalten vorhersehen können.

Was hat ein Hamster in der Mikrowelle damit zu tun?

Dazu kommen wir gleich. Lassen Sie mich vorher kurz aufdröseln, was wir mit personalisierten Webseiten, die sich automatisch und nach vorher festgelegten Regeln auf das Nutzerverhalten anpassen,  überhaupt erreichen können:

Komplexität verringern 

Sagt Ihnen der Begriff Decision Fatigue – bzw. Paradox of Choice etwas? Wissenschaftler gehen davon aus, dass wir mit einem festen Level an „Entscheidungsenergie“ in den Tag starten. Diese Energie nimmt mit jeder Entscheidung, die wir im Laufe des Tages treffen müssen ab. Es fällt uns immer schwerer neue Entscheidungen zu fällen und irgendwann wehren wir uns sogar vollständig dagegen noch weitere Entscheidungen zu machen.

Marmeladen-Paradox-of-Choice
(cc) Flickr-User Hellebardius

Dazu gab es im Jahr 2000 ein interessantes Experiment – das Marmeladen ExperimentIn einem Supermarkt wurden den Kunden an einem Tag 24 Sorten Marmelade angeboten und am nächsten Tag nur 6 Sorten. Das Ergebnis war verblüffend:

  • 24 Marmeladen zogen 60% der Kunden zum Stand. Aber: Nur 2% kauften. Die Auswahl war zu komplex.
  • 6 Marmeladen zogen nur 40% der Kunden an. Doch 12% der Kunden kauften aufgrund der einfacheren Entscheidungsfindung.

Personalisierte Webseiten können überflüssiges für den Kunden ausblenden, damit Entscheidungen leichter gefällt werden können.

Besucherverhalten steuern

Wenn wir eine Webseite mit einem speziellen Konversionsziel bauen, dann möchten wir dieses Ziel so oft wie möglich erreichen. Nehmen wir das Beispiel aus der u.s. Grafik: Der Benutzer soll sich zu einer kostenlosen 30-Tage-Demo anmelden. Der Nutzer wird zwischen verschiedenen Infoquellen immer wieder hin und her springen. Dabei auch unsere Kanäle verlassen und wieder zurückkehren.

Sitecore Customer Journey

 

Wir haben nun die Möglichkeit, unsere kostenlose Demo an unterschiedlichen Stellen und Arten immer wieder in den Fokus des Kunden zu bringen. Mit Anmeldekästen, Head-Bannern, kurzen Testimonials usw. bis der Besucher sich anmeldet

Ebenso können wir festlegen ab wann wir den Besucher nicht mehr oder nur noch weniger „nerven“ um eine Übersättigung zu vermeiden.

Bildschirmfoto 2014-09-04 um 12.46.23
Upgrad-Angebot im blauen Kasten kann nach Abschluss bsw. ausgeblendet werden

Wenn der Kunde schlussendlich unser Konversions-Ziel erfüllt hat, stellen wir die Erinnerungen daran ganz ab.

Wir erreichen so weniger komplexe Webseiten, die unsere Kunden einfacher Entscheidungen treffen lassen.

Wechselnde Geräte und Kanäle sind ein weiterer Anwendungsfall. Je nach erkanntem Gerät können andere Produkte, Inhalte oder Daten angezeigt werden. Nutzt jemand die Webseite der Deutschen Bahn bsw. mit dem Smartphone sind Unternehmensbeschreibungen vermutlich irrelevant – umso wichtiger dafür die aktuellen Fahrpläne. Ebenso können Textbausteine für große Bildschirme länger und umfangreicher sein, wobei dem Nutzer auf dem Smartphone-Display Übersicht und Muße zum Lesen fehlen.

Individuelles Storytelling

Diesen Punkt sehen wir uns gleich noch genauer an. Durch die vorab fest gelegten Klickpfade in einer automatisch personalisierbaren Webseite, lassen sich ganze Geschichten erzählen, drehbuchartig orchestriert. Mehr noch: Wir können unsere Nutzer quasi wie in einem Adventure-Computerspiel verschiedene Wege nehmen lassen, bei denen sich die Webseite an die individuellen Entscheidungen des Besuchers anpasst.

Das neue SEO?

Vermutlich ist es nicht zu weit aus dem Fenster gelehnt, wenn ich sage: Automatische Personalisierung könnte das neue SEO werden. Die Komplexität in den Einflussfaktoren ist vergleichbar hoch, die Auswirkungen vergleichbar gut und messbar.

Mit zwei wesentlichen Unterschieden:

  1. Im Bereich der SEO sind wir von den Vermutungen und Erkenntnissen abhängig, die wir über die Black-Box Suchmaschine erhalten
  2. Bei der Personalisierung spielt sich der Großteil unserer Anpassungsmöglichkeiten auf unseren eigenen Seiten ohne Einflüsse von außen ab

Wonach lässt sich personalisieren?

Die Faktoren sind schon heute irrsinnig komplex. Bereits in der Einzelbetrachtung. Hinzu kommen natürlich noch unendlich viele Möglichkeiten Einzelbedingungen miteinander zu kombinieren.

  • Handelt es sich bei einem Besucher um einen neuen Besucher oder um einen Wiederkehrenden? Ist der Benutzer angemeldet oder anonym? Habe ich CRM-Daten verknüpft?
  • Kommt der Klick aus meinem Newsletter? Dann zeige ich die dort geteaserten Angebote an und blende das Anmeldefenster für den Newsletter aus
  • IP-Adresse / Geo-Position können Maßgabe sein um landestypische Inhalte anzuzeigen oder auszublenden
  • Wetter am Ort des Besuchers: Verkaufe ich Skier und Surfbretter und am Standort meines Nutzers schneit es seit einem Tag sind eventuell Skier interessanter
  • Facebook-Fan JA/NEIN? Im Falle von NEIN zeigen wir unser „Werde Fan“-Banner an
  • Endgerät entscheidet darüber ob umfangreichere Texte angezeigt werden. Hochpreisige oder preiswerte Endgeräte können über das angezeigte Angebot entscheiden

Zwei Beispiele für automatische Personalisierung

Seitenbereiche nach Klickverhalten anpassen

In diesem Sitecore Beispiel wird dem Benutzer zunächst eine Webseite mit typischen Badeurlaub-Szenarien angezeigt:

Sitecore Webseiten Automatisierung Beispiel 1

Unser Beispielnutzer klickt nun aber nicht auf den Strand oder die Palmen, sondern interessiert sich für San Francisco. Wir haben vorher festgelegt, dass in diesem Fall ein anderer Klickpfad zur Verfügung gestellt wird und sich die 3 Themen-Angebote oben entsprechend darauf einstellen.

Die drei Kurzteaser wechseln vom Thema Strandurlaub zum Thema Städtereisen und stellen sich damit auf das vermeintliche Interessengebiet des Nutzers ein. (Auch um dieses Verhalten wieder rückgängig zu machen lassen sich Regeln erstellen):

Sitecore Webseiten Automatisierung Beispiel 2
Sitecore Webseiten Automatisierung Beispiel 2

Inhalte automatisch nach Benutzer-Standort anpassen

Dieses Beispiel stammt aus einem unserer eigenen Sitecore-Projekte für unseren Kunden Dornbracht. Dornbracht ist Premium-Hersteller u.a. für luxuriöse Badausstattungen und hat in diesem Zusammenhang eine Liegedusche im Portfolio, die Horizontal Shower. Dieses Produkt wird mit einer sehr stimmungsvollen Photographie auf der Webseite vorgestellt.

Inklusive einer unbekleideten Person, die gerade die Liege-Dusche verwendet:

Bildschirmfoto 2014-08-28 um 17.17.38

Nun ist es so, dass in manchen Teilen der Welt solche Abbildungen – auch im seriösesten Zusammenhang – als anstößig empfunden werden. Zum Beispiel im arabischen Raum, in dem sich auch ein relevanter Zielgruppenanteil für die Horizontal-Shower befindet. Wir haben also eine Lösung entwickelt, die nach 2 Kriterien entscheidet, wann eine Alternative angezeigt werden soll: Zum einen über die eingestellte Sprache (Englisch im arabischen Sprachraum) und die IP-Adresse.

Im Falle einer positiven Identifizierung wird die Webseite also mit folgender Abbildung ausgeliefert:

Bildschirmfoto 2014-08-28 um 17.17.11

Vorhersehen des Nutzerverhaltens

Eben habe ich schon einmal den Vergleich zum Thema SEO heran gezogen. Es gibt noch nicht viele Best Practices für umfangreich automatisierte Webseiten. Wir sprechen hier immer noch von einer Zukunftstechnologie – auch wenn die technischen Voraussetzungen bereits realisierbar sind.

Darum möchte ich zwei Beispiele aus dem Umfeld der Suchmaschinenwerbung heranziehen um zu demonstrieren, wie das Leben des Benutzers erleichtert werden kann und was es heißt, Nutzerverhalten vorhersehen zu können.

SEO = maschinenfokussiert – SEA = menschenfokussiert

Natürlich entwickelt sich SEO ständig weiter. Es wird zum einen komplexer und spezieller, zum anderen kommt man um SEO-Maßnahmen heutzutage nicht mehr herum. Mit Ausnahme vielleicht, wenn man keinen Wettbewerb hat.

Aber: SEO bezieht sich in den allermeisten Fällen auf den Umgang mit Rechnern, Suchmaschinen, Algorithmen. Deswegen wird das Thema Content Marketing immer wichtiger: Beim Content Marketing steht der Mensch, der Nutzer und Adressat des Contents im Mittelpunkt.

Beim SEA (also dem Suchmaschinen-Advertising) war – wie bei allen Werbeformen – der Mensch schon schon immer der zentrale Punkt. „Der Köder muss dem Fisch schmecken.“

Suchmaschinenwerbung über den Ort

Eine Möglichkeit der Personalisierung ist bsw. der Zielort einer Suche. Im folgenden Beispiel wurde nach Ferrari fahren Hamburg“ gesucht. In den darauf folgenden Suchergebnissen war eine auf Ferrari und Hamburg optimierte Landingpage angezeigt sowie eine auf die Suchbegriffe abgestimmte Google-Ads-Anzeige geschaltet.

Beide (rudimentär) personalisierten Wege führen den Besucher nun auf die entsprechende Webseite beim Anbieter, auf der nur Ferraris (statt Porsche) angezeigt werden, die in Hamburg verfügbar sind (statt auch in München bsw.). Im Dropdown-Menu ist Hamburg als Ort auch bereits vorausgewählt.

 

Dem Benutzer wird in diesem Fall vor allem zusätzliche Arbeit des Klickens abgenommen.

Königsklasse der Vorhersehung von Nutzerverhalten

Zugegeben, dieses Beispiel war sehr einfach. Ein meisterhaftes Stück in Sachen Nutzerverhalten antizipieren hat Alec Brownstein 2010 mit seinem Google Job Experiment gezeigt:

Alec sagte für sein „Projekt“ das Nutzerverhalten des Ego-Surfing voraus. Seine Zielgruppe bestand dabei nur aus 5 Personen: Er legte Google-Ad-Anzeigen auf die Namen der CEOs der 5 Top-Werbegenturen an. Wenn diese 5 Werbeagenturchefs nun sich selber googleten, wurde die Anzeige angezeigt (und wer klickt denn bitte schön nicht auf eine Anzeige, die den eigenen Namen enthält?) und führte auf Alex Brownsteins Bewerbung um einen Job in einer der Agenturen.

Bei 4 der 5 CEOs bekam Alex ein Vorstellungsgespräch. Daraus entstanden 2 Jobangebote. Eines davon nahm Alec an. Keine schlechte Konversion oder? 😉

Der Kostenaufwand betrug 6 Dollar.

Der Hamster ist ein historisches Meisterstück des Vorhersehens von Nutzerverhalten

Hervor gebracht hat dieses Meisterstück Ron Gilbert im Jahr 1987. Ron ist der Erfinder des Computerspiels Maniac Mansion. Und damit auch (Mit)-Erfinder des Genres Point-And-Click-Adventure. Die älteren unter uns erinnern sich hoffentlich noch an den guten, alten Commodore C-64 😉

(c) Lucas Arts - Poster Maniac Mansion, Zac McKracken, Monkey Island
(c) Lucas Arts – Poster Maniac Mansion, Zak McKracken, Monkey Island

Im Spiel Maniac Mansion musste man sich seinen Weg mit verschiedenen Spielfiguren durch ein verrücktes Spukhaus bahnen, das zudem von verrückten Aliens bewohnt wurde.  Ziel des Spiels war es die Freundin der Hauptfigur aus den Händen eines verrückten Wissenschaftlers zu befreien (haben wir ja alle schonmal erlebt, oder?).

Ron Gilbert hat letztens seinen alten Lagerraum aufgeräumt und dabei mit den Maniac Mansion Design Notes historische Relikte der Computerspielgeschichte wieder entdeckt, die uns heute durchaus als Vorlage und Best-Practices für die automatische Personalisierung dienen können.

So hat er bsw. die Original-Zeichnungen und Designdokumente veröffentlicht. So schön diese anzusehen sind, ist für uns aber wichtiger, wie vor über 25 Jahren die Planung des Spielablaufs von statten ging. Eines der Dokumente zeigt zum Beispiel wie die einzelnen Räume des Hause (heute auch Webseiten) miteinander verbunden sind und welche Figuren dort auf den Spieler (heute Inhalte) warten:

mm_design_3

Je nach Sympathie und Handlungen des Spielers reagierten die Persönlichkeiten in den Räumen unterschiedlich. Zu den reinen Räumen, Inhalten und Interaktionsmöglichkeiten kamen noch Emotions-Bedingungen hinzu:

mm_design_4

Schließlich wurden im Puzzle Dependency Charts die Bedingungen festgelegt, wann in welchen Räumen was passieren muss um die nächsten Schritte zu ermöglichen. In diesem Fall hier musste in einem Raum ein Schlüssel gefunden werden und in einem weiteren eine Kanne mit Öl. Der Schlüssel schloss die Kellertür auf, das Öl aus der Kanne machte die Tür wieder beweglich. So können auch verschiedene Bedingungen auf Webseiten zusammen „geschaltet“ werden, um eine weitere Aktion zu ermöglichen oder Interaktions-Möglichkeit anzuzeigen.

Bildschirmfoto 2014-09-10 um 13.28.08

Maniac Mansion ließ den Spieler eine Menge verrückter Dinge tun, die sich nicht unbedingt alle auf den eigentlichen Spielerfolg auswirkten. Dabei hat Ron Gilbert die skurrilsten Handlungen vorhergesehen.

Der arme Hamster

Kommen wir endlich zu unserem Beispiel-Nagetier:

Maniac Mansion Screenshot (tentakelvilla.de)
Maniac Mansion  (c) Lucas Arts Screenshot – Tentakelvilla.de

Man beachte das Poster an der Wand: Auf dem Poster neben der Tür des virtuellen Zimmer ist eine sehr vereinfachte Variante des Entscheidungsbaums der im Spiel zum Einsatz kommt abgebildet!

Zwischen diesem Poster und der Tür befindet sich der besagte Hamster in seinem Käfig. Diesen konnte man als Spieler mit dem Klick auf NIMM und dann das Objekt Hamster mitnehmen.

In der Küche des Maniac Mansion angelangt war es dem Spieler möglich, den Hamster in die Mikrowelle zu legen und das Küchengerät einzuschalten. Sehr morbider Humor. Zugegeben. Vermutlich würde sich das heute auch kein Spielehersteller mehr trauen.

Maniac Mansion gekochter Hamster (tentakelvilla.de)
Maniac Mansion gekochter Hamster (c) Lucas Arts – Screenshot Tentakelvilla.de

Es zeigt aber, wie gut Ron Gilbert damals bereits das Nutzer- bzw. Spielerverhalten vorhersehen konnte. Schließlich hatte die ganze Koch-Aktion des Hamsters überhaupt keinen weiteren Sinn im Spiel.

Was zeigt uns der Hamster für unsere Webseiten?

Mit einem gut und detailliert ausgearbeiteten Entscheidungsbaum lässt sich nicht nur Nutzerverhalten antizipieren, sondern eine Geschichte erzählen, die den Besucher ins Geschehen einbezieht, Bindung aufbaut und Begeisterung erzeugt. Wir können Fälle entdecken, die uns sonst nicht auffallen würden und das Verhalten der Webseite daran anpassen:

Was soll der Besucher im Fall X anderes sehen, als im Fall Y und welches Verhalten führt zu Fall Z?

„Das ist doch alles furchtbar viel Arbeit!“ höre ich Sie jetzt sagen. Und ja, Sie haben Recht. Webseiten zu personalisieren ist zu Anfang ein großer Brocken Arbeit und im folgenden ein stetiger Prozess. Der meiste Teil dieser Arbeit findet dabei im Kopf des Marketings-Teams statt.

Die gute Nachricht ist:

Es gibt einfache Werkzeuge um die geleistete Denkarbeit in die Webseite zu übertragen. Den Sitecore Engagement Plan zum Beispiel:

Sitecore Engagement Plan
Sitecore Engagement Plan

Das kommt Ihnen nun sicher bekannt vor? Unterscheidet sich vom Prinzip her nicht sonderlich von den Maniac Mansion Design-Dokumenten aus 1987.

Mit Sitecores Rule Editor werden Bedingungen für das Nutzerverhalten auf der Seite erstellt. Das Tool ist genauso leicht zu bedienen, wie der Filter-Assistent von Microsoft Outlook.

Sitecore Rule Editor
Sitecore Rule Editor

Zukunftsausblick

Es ist sicher nicht allzu vermessen davon auszugehen, dass Content Management Systeme in Zukunft in der Lage sein werden nach vorher festgelegten Algorithmen zu lernen und sich automatisch selbst an das Verhalten der Nutzer anzupassen. Amazon ist hier ja bsw. ein sehr bekannter Vorreiter („Kunden die diesen Artikel gekauft haben, kauften auch…“) Allerdings ist ein Algorithmus im weitesten Sinne und auf seine Grundbestandteile reduziert auch nichts anderes als ein Entscheidungsbaum, den man sich vorher im Kopf überlegt hat.

Unser praktischer Tip zum personalisieren von Webseiten daher:

Machen Sie es wie Gandhi. Versetzen Sie sich gedanklich in Ihre verschiedenen Benutzer und spielen Sie Ihre Webseite durch.

Dokumentieren Sie das Verhalten der Webseite mit einfachsten Mitteln: Zettel & Stift

Werkzeug zur Planung automatisierter Webseiten
Werkzeug zur Planung automatisierter Webseiten

Erstellen Sie so Entscheidungsbäume und Klickpfade, anhand derer Sie erkennen, wo Ihnen eine automatisch personalisierte Webseite einen Wettbewerbsvorteil in Form von mehr Umsatz, Einsparungen von Arbeit und Zeit sowie zufriedeneren Kunden bringen kann.

Ach und noch eine Sache:

Bei der Entwicklung solcher Klickdiagramme entdecken Sie möglicherweise auch unterhaltsame und skurrile Interaktionen wie den Hamster in der Mikrowelle. Solche Easter Eggs haben durchaus  das virale Zeug dazu, Ihre Besucher so zu begeistern, dass sie über 25 Jahre später noch an das Erlebnis auf Ihrer Webseite denken 😉 Das einfachste Beispiel ist hier wohl die Google-Sucheingabe „do a barrel roll“ oder falls Sie iPhone-Nutzer sind, stellen Sie Siri einmal die Frage: „Siri, was sagt der Fuchs?“ und danach fragen Sie einfach noch einmal 🙂 

 

Wenn Sie mehr über die Möglichkeiten von automatisch personalisierten Webseiten erfahren möchten, vereinbaren Sie hier ein unverbindliches Beratungsgespräch mit unseren Experten.

 

Was wurde eigentlich aus dem Hamsterkiller?

Die Auflösung bin ich Ihnen ja noch schuldig. Natürlich war der kleine Handlungsstrang mit dem gekochten Hamster in der Küche noch nicht beendet.

Geht man mit dem gekochten Hamster zurück in das Zimmer, aus dem man das Tierchen entwendete, steht dort Ed, der außerirdische Hamsterbesitzer neben dem leeren Käfig.

hamstergrill_11
(c) Lucas Arts – Screenshot von Tentakelvilla.de

 

Gibt man Ed nun den gekochten Hamster zurück, nimmt das Spiel ein jähes und berechtigtes Ende. Soll niemand sagen, dass Hamstermord nicht bestraft wird!

hamstergrill_12
(c) Lucas Arts – Screenshot von Tentakelvilla.de

Übrigens: Ron Gilbert ist einer der wenigen Menschen, der sich einmal (trotz vorheriger und eingehender Warnung dies nicht zu tun) mit Steve Jobs gestritten hat. Diese wunderbare Geschichte gibt es wie viele weitere Einblicke in die wunderbare Welt der Computerspiele drüben auf seinem Blog grumpygamer.com.

Den vollständigen Spielverlauf von Maniac Mansion in einzelnen Screenshots können Sie sich hier anschauen.

 

Sitecore CMS in der Cloud mit Microsoft Azure – Ein Fallbeispiel

Microsoft Azure Infografik

Ein Enterprise CMS-System wie Sitecore in der Cloud zu betreiben macht in vielen Fällen Sinn. Insbesondere bei regelmäßigen Lastspitzen oder bei weltweit verteilt betriebenen Webseiten. Azure ist Microsofts Cloud-Lösung, bringt automatisches Deployment von Webservern mit und unterstützt natürlich auch Microsoft SQL Datenbanken. Da Sitecore auf Windows-Server-Plattformen läuft, bietet sich hier eine genauere Prüfung einer kombinierten Lösung an.

Microsoft Azure Infografik
Microsoft Azure Infografik

Ein solches Vorhaben bringt einiges an Fragen, Anforderungen und Herausforderungen mit sich. Deswegen führten wir ein Testprojekt durch, bei dem unsere Kollegin Friederike die Kopie eines Kundenprojekts in die Azure Cloud umzog, um valide Erfahrungen mit dieser speziellen Lösungs-Kombination zu sammeln. Diese Erfahrungen haben wir in einem Test-Tagebuch festgehalten, aus dem wir Ihnen hier die wichtigsten Erkenntnisse vorstellen möchten.

Alles ist ein Service

Mittlerweile gibt es tatsächlich die Abkürzung XaaS bzw. EaaS – „Everything as a Service“ als Überbegriff für all die Leistungen wie Software, Plattformen, Infrastrukturen, Laufzeitumgebungen, Hardware und viele mehr, die sich als Services buchen und on demand beschaffen lassen.

Die generellen Hauptvorteile für Kunden beim Einsatz einer Cloud-Strategie sind:

  • Keine Bindung an physische Güter
  • Aktualität und Leistung von Hardware immer ausreichend
  • flexible Abrechnung nach Nutzungsintensität, -Dauer, Nutzeranzahl
  • keine Kapital-Bindung
  • geringe bis keine Wartungskosten

Die eingangs gezeigte Infographik von Microsoft (hier zum Download als PDF) illustriert sehr gut, welche Gesamtmöglichkeiten die Microsoft Azure Cloud-Services bieten. Wir konzentrieren uns hier auf einen kleinen Teilbereich.

Sitecore CMS in der Cloud – IaaS

Eine Telko mit dem Azure Vertrieb brachte zunächst Überraschendes hervor: Das Aufsetzen einer Sitecore Instanz dauert nur 7 Minuten. Weltweit! Das ist erstmal schwer zu glauben, stellte sich aber als Tatsache heraus.

Microsoft-Azure-Uebersicht

Aber: Das bedeutet im einzelnen das hinzu schalten / hochfahren einer weiteren Sitecore CD Instanz dauert 7 Minuten. Das basiert allerdings auf einer vollständig konfigurierten Publizierungsinstanz / Deployment Center. Dieses vorzubereiten und aufzusetzen (Sitecore Installation) und dann zu konfigurieren dauert natürlich länger. Diese Arbeit hätte man aber auch bei einer Installation im eigenen Rechenzentrum.

In einem unserer Testläufe haben wir Azure als IaaS (Infrastructure as a Service) getestet. Zum einen kann ein virtueller Server als „Quick Create“ aufgesetzt werden. Diesen kann man sich wie einen frisch installierten Rechner vorstellen.

Interessanter sind für uns in diesem Fall die vorkonfigurierten Server-Images aus einer Gallery. Wir entscheiden uns für Option A3 mit 4 CPU-Kernen und 7 Gigabyte Arbeitsspeicher. Übrigens ist als Serverstandort in Westeuropa nur Amsterdam oder Dublin möglich. Eine Standort-Option in Deutschland gibt es (zumindest noch) nicht.

Die Installation von Sitecore lief für unsere Experten an sich problemlos. Einzig an einigen Stellen musste die Dokumentation konsultiert werden:

  • diverse Module für den IIS Webserver nachinstallieren
  • Datenbankuser korrekt anlegen
  • korrekte Portangabe setzen

Kosten für den Installationsvorgang auf der virtuellen Maschine: 0,21 €

Zitat aus unserer Technik: „Hier habe ich genau die gleichen Malessen mit Lizenzen, Updates, Wartung, Administrierung wie im eigenen Rechenzentrum. Nur das Blech habe ich in diesem Fall nicht.“

Mehr können Sie dazu hier in der Dokumentation bei Microsoft erfahren.

Azure SQL wird in die Cloud ausgelagert – SaaS

Hier liegt nur die Datenbanksoftware in der Cloud. Dadurch wird das zu Grunde liegende Betriebssystem irrelevant. Dabei unterliegt Azure SQL einigen Unterschieden zur Microsoft SQL, wodurch sich die Datenbanken nicht so einfach migrieren ließen wie gewohnt.
In diesem SaaS-Fallbeispiel wird also nur ein Softwarebestandteil in der Cloud genutzt.
Wenn die Windows-Server sowieso zur Verfügung stehen, haben wir für dieses Modell keine direkte Anwendungsmöglichkeit in unserem Umfeld gefunden.

Sitecore CMS in der Cloud – PaaS

Sicherlich das spannendste Szenario. Hierzu haben wir zunächst die virtuelle IaaS Maschine kopiert und als Deployment Center benutzt. Natürlich hätten wir hierfür auch einen bereits lokal und physisch vorhandenen Server hernehmen können.

Sitecore Azure Traffic Manager

Dann wurde eine Kopie der Daten des Kundenprojekts, die wir freundlicherweise für unseren Test nutzen durften, in das Projekt migriert. Nach ca. einem Tag war die Migration der Daten (Languages, Templates, CoreDB, Files Package, Database Package und Configs) erfolgreich durch.
Sitecore wurde auf die aktuellste Version upgegradet.
Das Azure Modul wird schlussendlich installiert und konfiguriert.
Danach kann innerhalb von 7 Minuten per Klick ein Server hochgefahren werden. Ob in Hongkong, Dublin oder Australien ist dabei quasi unerheblich.
In diesem Fall liegt alles was wir benötigen bereits vorinstalliert als „Plattform“ in der Cloud:
  • Betriebssystem
  • IIS Webserver
  • lauffähiges Sitecore
  • und Datenbank als SaaS oder Datenbank-Server oder im eigenen Rechenzentrum“

Wenn der DNS-Eintrag auf den Azure Traffic-Manager und die Routings entsprechend angepasst sind, werden bspw. Anfragen aus Südostasien deutlich schneller bedient, als wenn diese Besucher auf einen Webserver in Deutschland geroutet würden, da der Traffic Manager als Geo-DNS fungiert und den Traffic intelligent je nach Standort der Benutzer umleitet.

Bei besonderen Lastspitzen geht das ganze Procedere übrigens auch automatisch.
Sprich:
Server werden nach Bedarf gestartet, wenn plötzlich der Traffic irgendwo auf der Welt hoch geht. (Wenn zum Beispiel ein Fernsehbeitrag in Australien gezeigt wird.) Genauso können stärkere Maschinen per Termin im Voraus gebucht werden. An Weihnachten, bei einer geschalteten Kampagne oder zum Produkt-Launch. Zum angegebenen Zeitpunkt werden demnach die Serverkapazitäten erhöht und nach Ablauf wieder gesenkt um auf smarte Weise Kosten zu sparen.

Aus welchen Gründen kann eine CMS-Instanz in der Cloud Sinn machen?

  • Admins sparen Hardware, Zeit, Geld, Lizenzen, Wartung. Backups aus der Cloud auf lokale Rechner sollte man sich natürlich trotzdem noch ziehen.
  • Entwickler können schnell mal ein volles Testsystem hochziehen für 1-3 Tage nutzen und dann wieder abschalten. Gezahlt wird zeitgenau abgerechnet anstatt für fünfstellige Summen neue Server zu kaufen.
  • Global verteilte Standorte sind on demand möglich und damit auch eine schnellere Auslieferung an Endnutzer.
  • Plötzlich ansteigender Traffic kann automatisiert und nach fein einstellbaren Regeln abgefangen werden.

Gibt es eine Kostenersparnis?

In unserem Beispiel könnte die Azure-Lösung einige Prozentpunkte günstiger sein als die vorhandene physische Struktur.
Aber:
Ein Umzug in die Cloud wäre ein umfangreiches Projekt, das momentan noch die Einsparungen auffressen würde.
Für neue Projekte könnte eine Cloudnutzung durchaus von Beginn an günstiger sein.

Qualitätssicherungssysteme und Entwicklungssysteme, die nur bei Bedarf genutzt werden, könnten in einem „Pay-as-you-Go“-Bezahlmodell durchaus zukünftig eine Ersparnis bedeuten.

Fakt ist, dass sich Anbieter von Cloudlösungen wie Google, Microsoft und Amazon – um nur einmal die großen zu nennen – quasi ständig neu unterbieten was die Kosten angeht oder den Funktionsumfang für den Kunden erweitern. Damit werden Cloud-Ansätze zunehmend attraktiver.

Unser Fazit:

Die Komplexität eines Cloud-Umzugs ist nicht zu unterschätzen und setzt eine sehr präzise Planung für einen konkreten Use-Case voraus. Je nach Use-Case kann bereits heute eine Kostenersparnis realisiert werden. Performance-Gewinn und -Optimierung ist auf jeden Fall möglich.

Interessieren Sie Details zu unseren Erfahrungen mit Sitecore in der Cloud? Nehmen Sie gerne Kontakt mit uns auf!

Weiterführende Informationen:

In einer hervorragenden 7-teiligen Blog-Serie beschäftigt sich Microsoft Architect Evangelist Holger Sirtl hier bei MSDN mit der Auswahl der einzelnen Ausführungsmodelle von Microsoft Azure anhand von verschiedenen Szenarien:
Teil 1: Überblick über die Ausführungsoptionen
Teil 2: Virtual Machines
Teil 3: Cloud Services
Teil 4: Websites
Teil 5: Mobile Services
Teil 6: Auswahl des besten Ausführungsmodells
Teil 7: Wechsel des Ausführungsmodells

Für die Kostenkalkulation eines Cloud-Projekts hat Microsoft einen Preisrechner veröffentlicht

Monatliche, kostenlose Webcasts zum Thema Azur bietet Microsoft hier an

Fallstudien zu Microsoft Azure finden Sie hier

Eine zusätzliche Beschreibung der Besonderheiten bei der Installation des Moduls Sitecore Azure finden Sie bei den schweizer Kollegen im namics-Blog