<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://waitingimpatiently.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://waitingimpatiently.com/" rel="alternate" type="text/html" /><updated>2026-01-28T20:31:47+00:00</updated><id>https://waitingimpatiently.com/feed.xml</id><title type="html">Waiting Impatiently</title><subtitle>Six Time Sitecore MVP 2017-2022 Marketing Technologist.</subtitle><author><name>Chris Auer</name></author><entry><title type="html">Enabling flows for Salesforce Integration user</title><link href="https://waitingimpatiently.com/enabling-flows-for-salesforce-integration-user/" rel="alternate" type="text/html" title="Enabling flows for Salesforce Integration user" /><published>2025-05-15T00:00:00+00:00</published><updated>2025-05-15T00:00:00+00:00</updated><id>https://waitingimpatiently.com/enabling-flows-for-salesforce-integration-user</id><content type="html" xml:base="https://waitingimpatiently.com/enabling-flows-for-salesforce-integration-user/"><![CDATA[<p>The Salesforce Integration user license provides an economical option for system-to-system integrations but arrives with significant constraints. Most notably, these users cannot execute Flows by default—a limitation that can obstruct automation efforts.</p>

<p>However, the restriction can be overcome through strategic permission configuration. The process involves five steps:</p>

<h2 id="step-1-create-permission-set">Step 1: Create Permission Set</h2>

<p>Establish a new permission set titled “Integration Permission Set” with no assigned license.</p>

<h2 id="step-2-create-integration-user">Step 2: Create Integration User</h2>

<p>Set up a dedicated user with the “Salesforce Integration” license and assign the “Salesforce API Only System Integration” profile.</p>

<h2 id="step-3-assign-permission-set-license">Step 3: Assign Permission Set License</h2>

<p>This represents the critical phase. The Salesforce API license defaults to severe restrictions. Navigate to “Permission Set License Assignments” and enable the “Salesforce API Integration” license—this restores standard functionality.</p>

<h2 id="step-4-enable-run-flows-permission">Step 4: Enable Run Flows Permission</h2>

<p>Access the Integration Permission Set’s App Permissions section and activate the “Run Flows” checkbox.</p>

<h2 id="step-5-assign-permission-set-to-user">Step 5: Assign Permission Set to User</h2>

<p>Complete the configuration by assigning your newly created permission set to the integration user through the Manage Assignments button.</p>

<p><strong>Note:</strong> Without enabling the permission set license in Step 3, attempting to assign the permission set generates an error message regarding incompatible user licenses.</p>]]></content><author><name>Chris Auer</name></author><category term="Salesforce" /><summary type="html"><![CDATA[The Salesforce Integration user license provides an economical option for system-to-system integrations but arrives with significant constraints. Most notably, these users cannot execute Flows by default—a limitation that can obstruct automation efforts.]]></summary></entry><entry><title type="html">xDB.Tracker Identifier Missing</title><link href="https://waitingimpatiently.com/xdb-tracker-missing/" rel="alternate" type="text/html" title="xDB.Tracker Identifier Missing" /><published>2020-09-11T00:00:00+00:00</published><updated>2020-09-11T00:00:00+00:00</updated><id>https://waitingimpatiently.com/xdb-tracker-missing</id><content type="html" xml:base="https://waitingimpatiently.com/xdb-tracker-missing/"><![CDATA[<p>A persistent bug in Sitecore xConnect involves contact identifier management during merge operations. When two contacts merge, the system must select which identifiers to retain, but it frequently discards the xDB.Tracker identifier entirely.</p>

<p>There are two key identifier types: the Alias identifier (a random GUID assigned at contact creation) and the xDB.Tracker (assigned only during web visits). The problem occurs when merging contacts—the system fails to preserve the xDB.Tracker, leaving contacts unable to process subsequent web visits.</p>

<p>When affected, users encounter an error stating “Contact…must have a tracker identifier.” This breaks tracking functionality until users clear their cookies, forcing them to essentially restart their session.</p>

<h2 id="the-solution">The Solution</h2>

<p>The solution involves creating a custom pipeline processor that executes before Sitecore’s standard conversion process. This processor checks for missing xDB.Tracker identifiers and regenerates them via xConnect API calls when necessary. This fix resolves approximately 60 daily errors down to roughly one occurrence every 4-5 days.</p>

<p>This approach is a temporary workaround—hopefully the community can help reproduce the underlying issue for official Sitecore resolution.</p>]]></content><author><name>Chris Auer</name></author><category term="xConnect" /><category term="Sitecore" /><category term="xDB" /><summary type="html"><![CDATA[A persistent bug in Sitecore xConnect involves contact identifier management during merge operations. When two contacts merge, the system must select which identifiers to retain, but it frequently discards the xDB.Tracker identifier entirely.]]></summary></entry><entry><title type="html">Are you losing your xDB data?</title><link href="https://waitingimpatiently.com/are-you-missing-xdb-data/" rel="alternate" type="text/html" title="Are you losing your xDB data?" /><published>2020-02-06T00:00:00+00:00</published><updated>2020-02-06T00:00:00+00:00</updated><id>https://waitingimpatiently.com/are-you-missing-xdb-data</id><content type="html" xml:base="https://waitingimpatiently.com/are-you-missing-xdb-data/"><![CDATA[<p>If you are on Sitecore 9.0 to 9.1.1 without patches, data loss may occur. Users should watch for specific error messages in their logs.</p>

<h2 id="expected-errors-in-sitecore-logs">Expected Errors in Sitecore Logs</h2>

<p>The system generates a message stating “ERROR General error when submitting contact. Exception: Sitecore.XConnect.Operations.FacetOperationException Message: Operation #0, AlreadyExists, <ContactId>, Classification Source: Sitecore.Xdb.Common.Web"</ContactId></p>

<h2 id="expected-errors-in-xconnect-logs">Expected Errors in xConnect Logs</h2>

<p>Similar FacetOperationException errors appear, indicating batch execution problems with contact classification operations.</p>

<h2 id="official-solution">Official Solution</h2>

<p>A patch exists in the Sitecore Knowledge Base addressing this contact-saving issue.</p>

<h2 id="persistent-problem-in-multi-server-environments">Persistent Problem in Multi-Server Environments</h2>

<p>Even with the patch installed, errors continue in specific configurations:</p>
<ul>
  <li>Multiple Content Delivery servers</li>
  <li>Load balancer implementation</li>
  <li>Session state stored in-process (not Redis, MongoDB, or SQL)</li>
</ul>

<h2 id="root-cause">Root Cause</h2>

<p>When clients switch between servers or devices, in-process sessions disconnect, severing the contact reference. New sessions attempting to save contacts generate duplicate operation errors.</p>

<h2 id="resolution">Resolution</h2>

<p>Move both shared and private session state to Redis, SQL Server, or MongoDB using Sitecore’s official configuration walkthroughs.</p>

<p><strong>Note:</strong> SQL implementations won’t function in Azure SQL due to temp database requirements.</p>]]></content><author><name>Chris Auer</name></author><category term="Sitecore" /><category term="xDB" /><category term="xConnect" /><summary type="html"><![CDATA[If you are on Sitecore 9.0 to 9.1.1 without patches, data loss may occur. Users should watch for specific error messages in their logs.]]></summary></entry><entry><title type="html">Bonfire releases xDB Peek (Part 2)</title><link href="https://waitingimpatiently.com/xdb-peek-part-2/" rel="alternate" type="text/html" title="Bonfire releases xDB Peek (Part 2)" /><published>2019-09-02T00:00:00+00:00</published><updated>2019-09-02T00:00:00+00:00</updated><id>https://waitingimpatiently.com/xdb-peek-part-2</id><content type="html" xml:base="https://waitingimpatiently.com/xdb-peek-part-2/"><![CDATA[<p>This installment continues from Part 1, diving into the breakdown of xDB Peek’s information categories and upcoming features.</p>

<h2 id="contact-section">Contact Section</h2>

<p>The contact tab houses all xConnect-related contact data, including:</p>

<p><strong>Identifiers</strong> - A comprehensive list of assigned identifiers and merged accounts, containing source, identifier value, type, and validity status.</p>

<p><strong>IsKnown</strong> - Indicates whether a contact has been identified using methods beyond Sitecore’s default identifiers, such as through the IdentifyAs() function or direct xConnect assignment.</p>

<p><strong>ExpandOptions</strong> - Displays available facets for xConnect interaction, functioning as a registry of known facets.</p>

<p><strong>ConcurrencyToken</strong> - A GUID that Sitecore applies to all facets. Mismatched tokens during save operations trigger an error, preventing facet overwrites. Each object possesses a unique token.</p>

<p><strong>LastModified</strong> - Timestamp of the most recent contact modification.</p>

<p><strong>Id</strong> - The primary contact identifier visible in Experience Profile URLs and the Contacts table within shard databases (distinct from tracker contact IDs).</p>

<h2 id="visit-data-section">Visit Data Section</h2>

<p>Current interaction information specific to the active web visit:</p>

<ul>
  <li><strong>BrowserInfo</strong> - Browser identification data including major name, minor name, and version.</li>
  <li><strong>ChannelId</strong> - Current visit’s assigned channel, variable based on traffic source.</li>
  <li><strong>DeviceId</strong> - Associated device identifier from Sitecore’s device registry.</li>
  <li><strong>GeoData</strong> - Geographic information derived from IP geolocation services (available free in Sitecore 9.x).</li>
  <li><strong>HasGeoIpData</strong> - Boolean indicating geolocation data availability.</li>
  <li><strong>InteractionId</strong> - Unique identifier for the specific web visit.</li>
  <li><strong>Ip</strong> - User’s IP address in hexadecimal format (requiring hex decoding).</li>
  <li><strong>Keywords</strong> - Keywords assigned to the interaction.</li>
  <li><strong>Language</strong> - Current visit’s language designation.</li>
  <li><strong>ScreenInfo</strong> - Device screen dimensions as Sitecore perceives them, based on browser-provided data.</li>
  <li><strong>SiteName</strong> - Identified Sitecore site from the sites configuration node.</li>
</ul>

<h2 id="pages-section">Pages Section</h2>

<p>Comprehensive listing of all pages visited during the current interaction, excluding pages from previous sessions. Contains page title, URL, and blank-window status.</p>

<h2 id="goals-section">Goals Section</h2>

<p>Records goals triggered during web visits or out-of-channel activities, displaying engagement value, title, UTC timestamp, current/past visit designation, and associated event data.</p>

<p><strong>CurrentGoals</strong> - Goals triggered within the current session, enabling Sitecore to personalize based on present-session activity.</p>

<p><strong>PastGoals</strong> - Goals triggered before the current visit, allowing personalization based on historical behavior. Current session goals transition to past goals upon visit closure.</p>

<h2 id="facets-section">Facets Section</h2>

<p>Lists all available contact facets populated from ExpandOptions. Example Personal facet contains birthdate, name components, gender, job title, language preference, concurrency token, and modification timestamp.</p>

<h2 id="profiles-section">Profiles Section</h2>

<p>Tracks current and historical pattern card assignments based on profile scoring:</p>

<p><strong>CurrentProfiles</strong> - Active pattern cards with profile name, score, count, and pattern details.</p>

<p><strong>PastProfiles</strong> - Historical pattern cards with scoring frequency, totals, and individual score records by key-value pairs.</p>]]></content><author><name>Chris Auer</name></author><category term="xDB" /><category term="Sitecore" /><summary type="html"><![CDATA[This installment continues from Part 1, diving into the breakdown of xDB Peek’s information categories and upcoming features.]]></summary></entry><entry><title type="html">Bonfire releases xDB Peek (Part 1)</title><link href="https://waitingimpatiently.com/xdb-peek/" rel="alternate" type="text/html" title="Bonfire releases xDB Peek (Part 1)" /><published>2019-09-02T00:00:00+00:00</published><updated>2019-09-02T00:00:00+00:00</updated><id>https://waitingimpatiently.com/xdb-peek</id><content type="html" xml:base="https://waitingimpatiently.com/xdb-peek/"><![CDATA[<p>Bonfire has unveiled xDB Peek, an evolved version of their analytics data transfer object project. This tool provides an accessible, styled interface for viewing comprehensive information about Sitecore website visitors.</p>

<h2 id="key-features">Key Features</h2>

<p>The tool displays:</p>
<ul>
  <li>xConnect Details</li>
  <li>Facets</li>
  <li>Goals</li>
  <li>Marketing Plans</li>
  <li>Campaigns</li>
  <li>History</li>
  <li>Patterns and profiles</li>
</ul>

<h2 id="background">Background</h2>

<p>The project originated in 2017 when James Williamson requested a way to identify a user’s profile during an active session without terminating it. The initial solution used a simple API endpoint (<code class="language-plaintext highlighter-rouge">/apis/v1/visitordetails</code>) that returned xConnect profile data in JSON format.</p>

<h2 id="evolution-to-xdb-peek">Evolution to xDB Peek</h2>

<p>The upgrade transforms this functionality into a user-friendly interface accessible without browser extensions. Instead of viewing raw JSON strings, data now organizes into distinct tabs for clarity. The tool supports both desktop and mobile viewing, recognizing that personalization experiences differ across devices.</p>

<h2 id="future-development">Future Development</h2>

<p>The team plans to expand beyond read-only capabilities, adding functions such as triggering goals, enrolling users in pattern cards, merging contacts, and executing other operational tasks.</p>

<p>The release targets Sitecore 9.x versions and is available on GitHub at the Bonfire repository.</p>]]></content><author><name>Chris Auer</name></author><category term="xConnect" /><category term="xDB" /><category term="Sitecore" /><summary type="html"><![CDATA[Bonfire has unveiled xDB Peek, an evolved version of their analytics data transfer object project. This tool provides an accessible, styled interface for viewing comprehensive information about Sitecore website visitors.]]></summary></entry><entry><title type="html">Add your xConnect facet to Experience Profile, the Lazy Way</title><link href="https://waitingimpatiently.com/add-facet-to-experience-profile-the-lazy-way/" rel="alternate" type="text/html" title="Add your xConnect facet to Experience Profile, the Lazy Way" /><published>2019-07-10T00:00:00+00:00</published><updated>2019-07-10T00:00:00+00:00</updated><id>https://waitingimpatiently.com/add-facet-to-experience-profile-the-lazy-way</id><content type="html" xml:base="https://waitingimpatiently.com/add-facet-to-experience-profile-the-lazy-way/"><![CDATA[<p>The challenge of displaying xConnect facets in Sitecore’s Experience Profile traditionally involves complex, time-consuming processes. I discovered a faster solution using the EP Express Tab, an open-source Sitecore project that enables adding tabs to Experience Profile in approximately 10 minutes.</p>

<p>The implementation involves three main steps:</p>

<h2 id="step-1-add-the-nuget-package">Step 1: Add the NuGet Package</h2>

<p>Install the EPExpressTab NuGet package to begin development.</p>

<h2 id="step-2-create-a-model-and-view-model">Step 2: Create a Model and View Model</h2>

<p>Build a model to hold your facets and other necessary data. Then construct a view model extending the EpExpressViewModel class, which specifies the CSHTML view location for the EP tab.</p>

<h2 id="step-3-design-the-cshtml-view">Step 3: Design the CSHTML View</h2>

<p>Create the presentation layer injecting into the new EP tab. I incorporated Sitecore’s styling to maintain visual consistency with Speak.</p>

<h2 id="how-it-works">How It Works</h2>

<p>EP Express Tab automatically detects classes inheriting EpExpressViewModel and generates corresponding tabs in the core database. The tab naming derives from the TabLabel property, and the rendering automatically integrates into Experience Profile’s presentation details.</p>

<p>For multiple tabs, developers simply create additional view models and views. The tab ordering can be adjusted within the core database at <code class="language-plaintext highlighter-rouge">/sitecore/client/Applications/ExperienceProfile/Contact/PageSettings/Tabs/</code>.</p>]]></content><author><name>Chris Auer</name></author><category term="xDB" /><category term="xConnect" /><category term="Sitecore" /><summary type="html"><![CDATA[The challenge of displaying xConnect facets in Sitecore’s Experience Profile traditionally involves complex, time-consuming processes. I discovered a faster solution using the EP Express Tab, an open-source Sitecore project that enables adding tabs to Experience Profile in approximately 10 minutes.]]></summary></entry><entry><title type="html">Working with the xConnect hex identifiers</title><link href="https://waitingimpatiently.com/convert-xconnect-hex-identifier/" rel="alternate" type="text/html" title="Working with the xConnect hex identifiers" /><published>2019-06-20T00:00:00+00:00</published><updated>2019-06-20T00:00:00+00:00</updated><id>https://waitingimpatiently.com/convert-xconnect-hex-identifier</id><content type="html" xml:base="https://waitingimpatiently.com/convert-xconnect-hex-identifier/"><![CDATA[<p>This article explains how to work with hexadecimal identifiers in Sitecore 9.x xConnect shard databases. Identifiers for contacts, contact facets, interactions, and interaction facets are now stored in separate tables with hexed values, unlike the Mongo structure used in Sitecore 8.2.</p>

<p>I needed to find a contact ID using a known email address. In the previous version, a simple Mongo query would retrieve this information. However, in 9.x, the identifiers are encoded in hexadecimal format.</p>

<p>Using an online hex-to-ASCII converter, I confirmed these are standard hex characters without encryption. Here are two SQL queries to work with this data:</p>

<h2 id="query-1-display-all-email-identifiers">Query 1: Display All Email Identifiers</h2>

<p>This query displays all email address identifiers in readable format using a CONVERT function to decode the hexadecimal values.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">CONVERT</span><span class="p">(</span><span class="nb">VARCHAR</span><span class="p">(</span><span class="mi">100</span><span class="p">),</span> <span class="n">Identifier</span><span class="p">)</span> <span class="k">as</span> <span class="n">Email</span>
<span class="k">FROM</span> <span class="p">[</span><span class="n">xdb_collection</span><span class="p">].[</span><span class="n">ContactIdentifiers</span><span class="p">]</span>
<span class="k">WHERE</span> <span class="k">Source</span> <span class="o">=</span> <span class="s1">'email'</span>
</code></pre></div></div>

<h2 id="query-2-find-specific-email">Query 2: Find Specific Email</h2>

<p>This query finds a specific email address by converting the search term to VARBINARY format and comparing it against the stored Identifier column.</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="p">[</span><span class="n">xdb_collection</span><span class="p">].[</span><span class="n">ContactIdentifiers</span><span class="p">]</span>
<span class="k">WHERE</span> <span class="n">Identifier</span> <span class="o">=</span> <span class="k">CONVERT</span><span class="p">(</span><span class="nb">VARBINARY</span><span class="p">(</span><span class="mi">100</span><span class="p">),</span> <span class="s1">'user@example.com'</span><span class="p">)</span>
</code></pre></div></div>

<p>This approach allows direct database access to retrieve contact information from the xConnect shard databases.</p>]]></content><author><name>Chris Auer</name></author><category term="Sitecore" /><category term="xConnect" /><category term="SQL" /><summary type="html"><![CDATA[This article explains how to work with hexadecimal identifiers in Sitecore 9.x xConnect shard databases. Identifiers for contacts, contact facets, interactions, and interaction facets are now stored in separate tables with hexed values, unlike the Mongo structure used in Sitecore 8.2.]]></summary></entry><entry><title type="html">What if I were to tell you the Sitecore.Kernel dll from NuGet isn’t the latest?</title><link href="https://waitingimpatiently.com/friendly-reminder-to-patch-your-sitecore-kernel/" rel="alternate" type="text/html" title="What if I were to tell you the Sitecore.Kernel dll from NuGet isn’t the latest?" /><published>2019-05-16T00:00:00+00:00</published><updated>2019-05-16T00:00:00+00:00</updated><id>https://waitingimpatiently.com/friendly-reminder-to-patch-your-sitecore-kernel</id><content type="html" xml:base="https://waitingimpatiently.com/friendly-reminder-to-patch-your-sitecore-kernel/"><![CDATA[<p>Sitecore maintains an extensive knowledge base containing patches and updates necessary for various environments. The manner in which sites are patched carries significant importance, requiring consistency across all instances.</p>

<p>In Sitecore 8.2 Update 6 and 7, as well as 9.1 Update 1, the kernel contains a bug that crashes when encountering bad internal links. This malfunction can either crash the Rebuild Link Database application or bring down an entire site. When Sitecore attempts to resolve a link without proper error handling, it can fail deep within kernel code, producing a “System.FormatException: Unrecognized Guid format” error.</p>

<h2 id="the-patching-challenge">The Patching Challenge</h2>

<p>The solution involves a Sitecore knowledge base patch that completely replaces the Sitecore.Kernel dll. However, this presents a patching challenge: Sitecore does not publish hotfixes through NuGet packages; they release fixes through their knowledge base for selective implementation.</p>

<h2 id="two-approaches">Two Approaches</h2>

<ol>
  <li>Include the patched kernel in builds</li>
  <li>Exclude it entirely and patch servers manually</li>
</ol>

<p>I advocate for the first option, emphasizing intentional CI builds that eliminate snowflake servers—environments with undocumented, manual patches.</p>

<h2 id="recommended-solution">Recommended Solution</h2>

<p>Create an Infrastructure.Patch project within Helix solutions to manage all patches centrally. This approach ensures consistency across environments and simplifies upgrades. By incorporating patches directly into build processes, organizations can achieve their goal of rebuilding production environments entirely through CI scripting.</p>]]></content><author><name>Chris Auer</name></author><category term="Sitecore" /><category term="CI" /><summary type="html"><![CDATA[Sitecore maintains an extensive knowledge base containing patches and updates necessary for various environments. The manner in which sites are patched carries significant importance, requiring consistency across all instances.]]></summary></entry><entry><title type="html">9.1 Release of the Bonfire Analytics DTO</title><link href="https://waitingimpatiently.com/9-1-release-of-the-bonfire-analytics-dto/" rel="alternate" type="text/html" title="9.1 Release of the Bonfire Analytics DTO" /><published>2019-04-09T00:00:00+00:00</published><updated>2019-04-09T00:00:00+00:00</updated><id>https://waitingimpatiently.com/9-1-release-of-the-bonfire-analytics-dto</id><content type="html" xml:base="https://waitingimpatiently.com/9-1-release-of-the-bonfire-analytics-dto/"><![CDATA[<p>I needed to monitor what Sitecore observes about users and sessions, encompassing goals, events, profiles, patterns, pages, geographic data, marketing automation, and xConnect facets—both current and historical versions.</p>

<p>I originally created a JSON application for version 8.2 and have maintained it through the 9.1 release cycle.</p>

<h2 id="key-feature-handling-sitecore-facets">Key Feature: Handling Sitecore Facets</h2>

<p>The system retrieves requested facets through ContactExpandOptions. My approach involves accessing the xConnect server configuration to obtain all KnownModels (available facet models), passing these into ContactExpandOptions to retrieve and serialize all facets.</p>

<h2 id="json-output-includes">JSON Output Includes</h2>

<p>The resulting JSON output includes:</p>
<ul>
  <li>Identifiers</li>
  <li>Contact status</li>
  <li>Visited pages</li>
  <li>Interaction details</li>
  <li>Current and past goals</li>
  <li>Current and past events</li>
  <li>xConnect facets with values</li>
  <li>Current profile identification</li>
  <li>Past profile identification</li>
</ul>

<p>Check the GitHub releases page for access to the tool.</p>]]></content><author><name>Chris Auer</name></author><category term="xConnect" /><category term="Sitecore" /><summary type="html"><![CDATA[I needed to monitor what Sitecore observes about users and sessions, encompassing goals, events, profiles, patterns, pages, geographic data, marketing automation, and xConnect facets—both current and historical versions.]]></summary></entry><entry><title type="html">Reset a facet on an xConnect contact</title><link href="https://waitingimpatiently.com/reset-a-facet-on-an-xconnect-contact/" rel="alternate" type="text/html" title="Reset a facet on an xConnect contact" /><published>2019-02-08T00:00:00+00:00</published><updated>2019-02-08T00:00:00+00:00</updated><id>https://waitingimpatiently.com/reset-a-facet-on-an-xconnect-contact</id><content type="html" xml:base="https://waitingimpatiently.com/reset-a-facet-on-an-xconnect-contact/"><![CDATA[<p>This article addresses a technical challenge in Sitecore 9.x regarding facet management on xConnect contacts. In the earlier 8.2 version, developers could use a <code class="language-plaintext highlighter-rouge">.Reset()</code> extension method to clear facets, but this functionality was removed in 9.x.</p>

<h2 id="the-problem">The Problem</h2>

<p>When attempting to replace an existing facet with a new instance, developers encounter the error “Facet already exists on the contact.” This occurs because xConnect tracks facets using a <code class="language-plaintext highlighter-rouge">ConcurrencyToken</code> to maintain data integrity and prevent unauthorized overwrites.</p>

<h2 id="the-solution">The Solution</h2>

<p>Rather than manually resetting each property to its default value, I created a custom extension method. The extension creates a fresh facet instance while preserving the original <code class="language-plaintext highlighter-rouge">ConcurrencyToken</code> through reflection:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">public</span> <span class="k">static</span> <span class="n">T</span> <span class="n">GetFacetWithDefaultValues</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;(</span><span class="k">this</span> <span class="n">T</span> <span class="n">facet</span><span class="p">)</span> <span class="k">where</span> <span class="n">T</span> <span class="p">:</span> <span class="n">Facet</span><span class="p">,</span> <span class="k">new</span><span class="p">()</span>
<span class="p">{</span>
    <span class="kt">var</span> <span class="n">newFacet</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">T</span><span class="p">();</span>
    <span class="kt">var</span> <span class="n">concurrencyTokenProperty</span> <span class="p">=</span> <span class="k">typeof</span><span class="p">(</span><span class="n">Facet</span><span class="p">).</span><span class="nf">GetProperty</span><span class="p">(</span><span class="s">"ConcurrencyToken"</span><span class="p">);</span>
    <span class="kt">var</span> <span class="n">originalToken</span> <span class="p">=</span> <span class="n">concurrencyTokenProperty</span><span class="p">.</span><span class="nf">GetValue</span><span class="p">(</span><span class="n">facet</span><span class="p">);</span>
    <span class="n">concurrencyTokenProperty</span><span class="p">.</span><span class="nf">SetValue</span><span class="p">(</span><span class="n">newFacet</span><span class="p">,</span> <span class="n">originalToken</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">newFacet</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This approach copies the concurrency token from the existing facet to a newly instantiated facet, allowing xConnect to accept the replacement without triggering integrity validation errors.</p>

<p>The solution also includes functionality for cases where developers want to swap in a pre-populated facet while maintaining the concurrency token.</p>]]></content><author><name>Chris Auer</name></author><category term="xDB" /><category term="xConnect" /><category term="Sitecore" /><category term="Facets" /><summary type="html"><![CDATA[This article addresses a technical challenge in Sitecore 9.x regarding facet management on xConnect contacts. In the earlier 8.2 version, developers could use a .Reset() extension method to clear facets, but this functionality was removed in 9.x.]]></summary></entry></feed>