Sitecore 9の環境で、ウェブサイト上で収集した個人のプロフィールをxDBに登録する方法のメモを記載します。登録した内容は Experience Profile アプリケーションで確認できるようになります。
今回のサンプルは、Set contact facets のドキュメントを参考に実装しています。
動作確認環境は Sitecore 9.1 Initial Release のスタンドアロン環境です。この記事は、Sitecoreの開発の知識(SXSDトレーニングを修了した程度の知識) を有していることを前提としています。そのため、Sitecoreの開発に関する基本的な手順は省いています。
1. フォームの準備
何はともあれ、ユーザーの名前を登録するフォームを作成します。今回はモデルクラスとしてユーザーの名前を格納するシンプルなクラスを定義しました。
public class UserProfile { public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; }
次に、コントローラーレンダリング(XProfileController)とアクションメソッド(UpdateFacets)を次のように定義しました。ファセットは、XConnectFacets に記録されていますので、 GetFacets メソッドを使用してファセットの参照を取得しています。氏名などの情報は PersonalInfomation ファセットに格納されているので、 PersonalInformation.DefaultFacetKey プロパティを使って、既定のファセット名を指定して参照を取得します。このとき、ファセットキーに対応するファセットが未登録の場合はエラーが発生するので、ファセットの登録有無を確認しています。あとは、ファセットのプロパティをモデルに設定してビューに渡しているだけです。
public class XProfileController : Controller { public ActionResult UpdateFacets() { var userprofile = new UserProfile(); var xConnectFacets = Tracker.Current.Contact.GetFacet<IXConnectFacets>("XConnectFacets"); if (xConnectFacets.Facets != null && xConnectFacets.Facets.ContainsKey(PersonalInformation.DefaultFacetKey)) { var personel = xConnectFacets.Facets[PersonalInformation.DefaultFacetKey] as PersonalInformation; userprofile.FirstName = personel.FirstName; userprofile.LastName = personel.LastName; } return View(userprofile); } }
あとは、UpdateFacets.cshtml 部分ビューを次のように作成しました。
@model SCSample.Models.UserProfile <h2>プロフィール編集</h2> @if (Sitecore.Analytics.Tracker.Current.Contact.IsNew) { <h3>New Contact</h3> } else { <h3>Existing Contact</h3> } @using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.LabelFor(m => m.FirstName) @Html.TextBoxFor(m => m.FirstName) <br/> @Html.LabelFor(m => m.LastName) @Html.TextBoxFor(m => m.LastName) <br/> <input type="submit" value="登録" /> }
コントローラレンダリングをSitecoreに登録して、任意のページで表示すると次のようなマークアップがレンダリングされます。
2. 更新処理の実装
XProfileController に、Postメッセージ処理用のアクションメソッドと、プロフィールを更新するためのメソッドを次のように実装しました。
xDBでのコンタクトレコードの登録の有無をTracker.Current.Contact.IsNew プロパティでチェックし、メソッドを分けています。未登録の場合は、xDB上にまずコンタクトレコードを作成するという処理を行ってから、プロフィール情報を更新するコードを実装しています。プロフィールを実装するファセットは、ContactManagerを使用して更新します。Sitecore 8と異なり、コンタクトのロックを取得しないアーキテクチャーになっているので、xDB上のプロフィールを変更したら、オンラインのコンタクトデータをリロードしてあげる必要があります。コード例では、リロードするコードも実装されています。
[HttpPost] [ValidateAntiForgeryToken] public ActionResult UpdateFacets(UserProfile model) { if (!ModelState.IsValid) { return View(model); } if (Tracker.Current.Contact.IsNew) { // 初めてサイトを訪問したコンタクト UpdateNewContactProfile(model); } else { // 再訪した訪問者 UpdateExistingContactProfile(model); } return View(model); } /// <summary> /// 既存(2回目以降の訪問者のプロフィールを更新 /// </summary> /// <param name="model"></param> /// <returns></returns> private bool UpdateExistingContactProfile(UserProfile model) { var manager = Sitecore.Configuration.Factory.CreateObject("tracking/contactManager", true) as Sitecore.Analytics.Tracking.ContactManager; if (manager != null) { Sitecore.Analytics.Model.Entities.ContactIdentifier anyIdentifier = Tracker.Current.Contact.Identifiers.FirstOrDefault(); using (XConnectClient client = SitecoreXConnectClientConfiguration.GetClient()) { try { Sitecore.XConnect.Contact contact = client.Get<Contact>( new IdentifiedContactReference(anyIdentifier.Source, anyIdentifier.Identifier) , new ExpandOptions(PersonalInformation.DefaultFacetKey)); if (contact != null) { PersonalInformation personal = contact.Personal() ?? new PersonalInformation(); personal.FirstName = model.FirstName; personal.LastName = model.LastName; personal.Birthdate = DateTime.Today.AddYears(-20); client.SetFacet<PersonalInformation>(contact, PersonalInformation.DefaultFacetKey, personal); client.Submit(); // 共有セッションからコンタクトデータを削除し、以降のページリクエスト時にリロードさせる manager.RemoveFromSession(Tracker.Current.Contact.ContactId); Tracker.Current.Session.Contact = manager.LoadContact(Tracker.Current.Contact.ContactId); } } catch (XdbExecutionException ex) { Sitecore.Diagnostics.Log.Error("error", ex, this); return false; } } } return true; } private bool UpdateNewContactProfile(UserProfile model) { var manager = Sitecore.Configuration.Factory.CreateObject("tracking/contactManager", true) as Sitecore.Analytics.Tracking.ContactManager; if (manager != null) { // xDB状にコンタクトレコードがないので、作成する Sitecore.Analytics.Tracker.Current.Contact.ContactSaveMode = ContactSaveMode.AlwaysSave; manager.SaveContactToCollectionDb(Tracker.Current.Contact); // コンタクトが保存されたので、ロード (9.0の場合は、"xDB.Tracker" を IdentifierSource の代わりに指定 var trackerIdentifier = new IdentifiedContactReference(Sitecore.Analytics.XConnect.DataAccess.Constants.IdentifierSource, Tracker.Current.Contact.ContactId.ToString("N")); using (XConnectClient client = SitecoreXConnectClientConfiguration.GetClient()) { try { var contact = client.Get<Contact>(trackerIdentifier, new Sitecore.XConnect.ContactExpandOptions()); if (contact != null) { PersonalInformation personal = contact.Personal() ?? new PersonalInformation(); personal.FirstName = model.FirstName; personal.LastName = model.LastName; personal.Birthdate = DateTime.Today.AddYears(-34); client.SetFacet<PersonalInformation>(contact, PersonalInformation.DefaultFacetKey, personal); client.Submit(); // 共有セッションからコンタクトデータを削除し、以降のページリクエスト時にリロードさせる manager.RemoveFromSession(Tracker.Current.Contact.ContactId); Tracker.Current.Session.Contact = manager.LoadContact(Tracker.Current.Contact.ContactId); } } catch (XdbExecutionException ex) { Sitecore.Diagnostics.Log.Error("error", ex, this); return false; } } } return true; }
これで準備は完了です。ちなみにコンタクトデータをリロードしても2回訪問したことにならないので安心してください。
3. 動作確認
フォームに名前を入力して、登録しています。
登録が成功するとコレクションデータベースのContactFacetsテーブルにファセットデータがPersonal というキーを使用して登録されていることを確認できるはずです。
FacetDataカラムはJSON形式になっているので、例えば次のようにデータが格納されます。
個人が特定されているコンタクト(Identified contact) の場合は、xProfile からコンタクトを検索して、登録されたプロフィールを確認できます。
簡単ですが、説明は以上です。
xDB上にコンタクトのデータを登録する場合は基本的にドキュメントサイトのコード例を参考にすれば簡単に実装することができます。
組み込みのファセットの一覧は、Use core collection model facets にあります。カスタムファセットの作り方は、Create a custom facet を参照できます。
さんのコメント: さんのコメント: