Get rid of empty html tags in Sitecore SXA

This blog is about how can we stop rendering of empty html tags in Sitecore SXA. Thank you Nathan Hase for your suggestion to use Rule Engine.

Issue:

We have hero component which has following rendering/html structure.

Now if you notice the Hero Headline, it has a wrapper div. So, the title will be rendered in following html structure.

Now what if there is no content in Headline field. The same structure will be rendered without Headline value.

You can see, empty h1 tag and its parent div tag. And we don’t want that.

 

Solution:
Sitecore SXA provides OOTB solution for this.

We need to update two things:

  1. The field itself i.e. Variant field.
  2. Its parent div which is wrapper/Variant Section

If you select Variant field, you can see checkbox Render if empty in Variant Details Section.

Make sure it is not checked/ticked. This means, it will not render – if it is empty (means field-name mentioned in this Variant Field is not having any value).

 

Now let’s update wrapper/variant section i.e. HeaderWrapper:

  1. Select the Variant Section item.
  2. You can see Rules section. It means that this Variant Section will be enabled only if the mentioned rule is true. Click on Edit rule.
  3. Search for field and under Fields related rule, click on “where the specific field is empty” rule.
  4. In the selected rule, click on “specific” text and enter the field name (in this context it is HeroHeadline).
  5. Now this means, if HeroHeadline field is empty, section will be enabled. But we want a rule which is completely opposite. Click on “where” and it will get converted into “except where”.

    So now, our rule is correct i.e. Enable the section except where the “HeroHeadline” field is empty.You can add multiple rules.
  6. Publish the Variant.

Now, empty h1 tag and its parent div tag will not get rendered.

That’s it.

Happy Coding 🙂

Advertisements

Things to consider while integrating Sitecore and Salesforce

This year at SUGCON India, me and my colleague Varun Shringarpure presented a session on how to connect Sitecore with Salesforce using Sitecore-Salesforce Connector.

sitecore connect

Here are some points which you need to consider before working/finalizing the integration:

Available Connectors:

  • You need to understand that Salesforce is not one system. It has four parts:
    • Sales Cloud
    • Marketing Cloud
    • Service Cloud
    • Community Cloud

First find out which system you are connecting Sitecore to? There are only two connectors are available from Sitecore:

  1. for Sales-cloud : Sitecore Connect for Salesforce CRM
  2. for Marketing-cloud : Sitecore Connect for Salesforce Marketing Cloud

As of now, no connector is available for Service and Community Cloud from Sitecore. We will here more on Service and Community Cloud in future from Sitecore.

Well, Sitecore Connector is not only connector available in market. Many third party connectors available in Market. FuseIT is one of them. During Sugcon India 2019, I got a chance to talk with Mr. Duane Franklet – Director of Operations at FuseIT and we have discussed various functionality FuseIT connector offers. It is very user-friendly tool available in the market.

The main advantage of using Sitecore Connector is Support, Strong road map and Strong partnership ahead.

 

License:

  • Sitecore Salesforce Connector needs a separate license from Sitecore. If you need more details, you need to talk with your Sitecore representative.
  • Also, the other available Connectors in the Market Place are not free.
  • So before recommending any of the connector or trying to plan for it, you should consider licensing.

Versions:

  • Different versions of Sitecore Salesforce Connector are available to support the respective sitecore instance. But to use latest features, it is recommended that you use latest Sitecore version and its compatible latest connector version.

Pre requisites:

  • You need to read all the pre-requisites instruction available installation guide of the Salesforce connector carefully. If you miss any of those, it will cause issue for sure.

Customization:

  • In terms of sitecore, xConnect platform is the area where customization is mostly possible using custom facets. Custom facet might contain additional attributes which one can customize.
  • In terms of salesforce, you can easily create some custom fields.
  • You need to take care of the mappings b/w sitecore and salesforce and make sure to define unique identifier between these two systems for example sitecore id.

 

That’s it. Best of luck for Integration.

Happy Coding 🙂

Install-SitecoreConfiguration : The certificate does not have a property that references a private key

I was trying to install Sitecore 9.0 update 1 instance on a local machine where I am already having couple of 9.0 instances. While installation, I was facing Certificate error, specifically at the time of Creating certificate of xConnect site: Install-SitecoreConfiguration : The certificate does not have a property that references a private key

image

I have checked Log file, in my case it is xconnect-createcert log file. I found following error.

[----------------------------------------------------- CreateSignedCert : NewSignedCertificate -------------------------------------------------]
VERBOSE: Resolving ConfigFunction extension 'GetCertificate'
VERBOSE: Resolved 'Invoke-GetCertificateConfigFunction'
VERBOSE: Invoke-GetCertificateConfigFunction
VERBOSE: Id: DO_NOT_TRUST_SitecoreRootCert
VERBOSE: CertStorePath: cert:\LocalMachine\Root
VERBOSE: Found Cert with thumbprint: 01C12329C899F2B535258E3C15BBC3D56B20D7D4
VERBOSE: Performing the operation "New-SignedCertificate: New signed certificate for sc901.local.xconnect_client" on target "c:\certificates".
VERBOSE: Searching certificates in cert:\LocalMachine\My for Name sc901.local.xconnect_client
VERBOSE: Failed to find certificate with Name sc901.local.xconnect_client
VERBOSE: New-SignedCertificate: Create a signed certificate for 'sc901.local.xconnect_client'
VERBOSE: New-SignedCertificate: Using PKI parameters for Windows Server 2016 and Windows 10
**********************
Command start time: 20180619121947
**********************
PS>TerminatingError(New-SelfSignedCertificate): "The certificate does not have a property that references a private key. 0x8009200a (-2146885622 CRYPT_E_UNEXPECTED_MSG_TYPE) CertEnroll::CSignerCertificate::Initialize: Cannot find object or property. 0x80092004 (-2146885628 CRYPT_E_NOT_FOUND)"
>> TerminatingError(New-SelfSignedCertificate): "The certificate does not have a property that references a private key. 0x8009200a (-2146885622 CRYPT_E_UNEXPECTED_MSG_TYPE) CertEnroll::CSignerCertificate::Initialize: Cannot find object or property. 0x80092004 (-2146885628 CRYPT_E_NOT_FOUND)"
Install-SitecoreConfiguration : The certificate does not have a property that references a private key. 0x8009200a 
(-2146885622 CRYPT_E_UNEXPECTED_MSG_TYPE) CertEnroll::CSignerCertificate::Initialize: Cannot find object or property. 
0x80092004 (-2146885628 CRYPT_E_NOT_FOUND)
At C:\SCResources\SCReources9_1_171219\InstallSitecore.ps1:40 char:1
+ Install-SitecoreConfiguration @certParams -Verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
 + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Install-SitecoreConfiguration
Install-SitecoreConfiguration : The certificate does not have a property that references a private key. 0x8009200a (-2146885622
CRYPT_E_UNEXPECTED_MSG_TYPE) CertEnroll::CSignerCertificate::Initialize: Cannot find object or property. 0x80092004 (-2146885628
CRYPT_E_NOT_FOUND)
At C:\SCResources\SCReources9_1_171219\InstallSitecore.ps1:40 char:1
+ Install-SitecoreConfiguration @certParams -Verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
 + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Install-SitecoreConfiguration

[TIME] 00:00:03
**********************
Windows PowerShell transcript end
End time: 20180619121948
**********************

 

I have googled this issue but unfortunately, not able to find any specific solution which solves this issue. Then I raised Sitecore Support ticket, and our great Sitecore Support Team (Mr. Michael Toh) came for rescue and has provided the solution:

Solution:

  1. Go to mmc > Add/Remove Snap in > Certificates > Computer Account > Local Computer;
  2. Delete following certificate (if exist) under “Personal/Certificates” and “Trusted Root Certification Authorities/Certificates”;
    • *.xconnect
    • *.xconnect_client
    • <Sitecore9 site name>
    • DO_NOT_TRUST_SitecoreFundamentalsRoot
    • DO_NOT_TRUST_SitecoreRootCert
  3. Go to mmc > Add/Remove Snap in > Certificates > Computer Account > My user account;
  4. Repeat step (2);
  5. Go to C:\certificates, delete all *.crt files;

This is basically clean up all Sitecore Certificates. Make sure,you should not delete the certificate specific to your existing sites.

Thank you Sitecore Support team for solving this weird issue. Hope, this will helpful to others to save their day.

Happy Sitecoring… version 9.0 🙂

Basics of xConnect – Step 6 – Create Interaction

An interaction is the point where contact interacts with the application/organization like Login, Adding item to the Cart or placing order via phone, Payment or just simply browsing the site.

Sitecore.XConnect.Interaction is the class using which, Interaction can be created.

To create interaction, following are the mandatory proeprties you need to pass:

  • Initiator
  • ChannelId
  • UserAgent

Initiator: who initiates the interaction. Either the user/contact or the application

ChannelId: Through which channel contact interact with the application/organization. Channels are represented as items under Sitecore CMS content tree /sitecore/system/Marketing Control Panel/Taxonomies/Channel.

UserAgent: User Agent which every device used to connnect the xConnect web service

For more information on Interaction, have a look at https://doc.sitecore.net/developers/xp/xconnect/xconnect-model/interactions.html

Lets initiate the Interaction now,….

I have already created one goal and channel in the Sitecore Marketing Control Panel.  The variable offlineGoal and channelId in following code are refering to those items.

                //Interaction
                var offlineGoal = Guid.Parse("A9948719-E6E4-46D2-909B-3680E724ECE9");//offline goal - KioskSubmission goal
                var channelId = Guid.Parse("3FC61BB8-0D9F-48C7-9BBD-D739DCBBE032"); // /sitecore/system/Marketing Control Panel/Taxonomies/Channel/Offline/Store/Enter store - offline enter storl channel
                //Create a new interaction for that contact
                Interaction interaction = new Interaction(knownContact, InteractionInitiator.Contact, channelId, "");
                // Add events - all interactions must have at least one event
                var xConnectEvent = new Goal(offlineGoal, DateTime.UtcNow);
                interaction.Events.Add(xConnectEvent);
                //Add interaction to client
                client.AddInteraction(interaction);

After adding this final segment, the method createUpdateContact() would finally look like following:

        public void createUpdateContact()
        {
            //Certificate
            CertificateWebRequestHandlerModifierOptions options =
            CertificateWebRequestHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=587d948806e57cf511b37a447a2453a02dfd3686");
            var certificateModifier = new CertificateWebRequestHandlerModifier(options);

            //Model - xConnect Client Configuration
            List clientModifiers = new List();
            var timeoutClientModifier = new TimeoutHttpClientModifier(new TimeSpan(0, 0, 20));
            clientModifiers.Add(timeoutClientModifier);

            // This overload takes three client end points - collection, search, and configuration
            var collectionClient = new CollectionWebApiClient(new Uri("https://sc9.xconnect/odata"), clientModifiers, new[] { certificateModifier });
            var searchClient = new SearchWebApiClient(new Uri("https://sc9.xconnect/odata"), clientModifiers, new[] { certificateModifier });
            var configurationClient = new ConfigurationWebApiClient(new Uri("https://sc9.xconnect/configuration"), clientModifiers, new[] { certificateModifier });

            var config = new XConnectClientConfiguration(
                new XdbRuntimeModel(CollectionModel.Model), collectionClient, searchClient, configurationClient);
            //initialize the configuration
            config.Initialize();

            //create the xConnect Client
            using (Sitecore.XConnect.Client.XConnectClient client = new XConnectClient(config))
            {
                // Identifier
                var identifier = new ContactIdentifier[]
                {
                    new ContactIdentifier("HIxConnect", "contact.name@demo.com", ContactIdentifierType.Known)
                };

                //Contact & Facets
                // Create a new contact with the identifier
                Contact knownContact = new Contact(identifier);
                client.AddContact(knownContact);

                //Facets
                #region Personal Information Facet
                //Persona information facet
                PersonalInformation personalInfoFacet = new PersonalInformation();
                personalInfoFacet.Title = ddTitle.SelectedValue;
                personalInfoFacet.FirstName = "Alok";
                personalInfoFacet.MiddleName = "S";
                personalInfoFacet.LastName = "KaduDeshmukh";
                personalInfoFacet.PreferredLanguage = "en";
                personalInfoFacet.Gender = "Male";
                personalInfoFacet.JobTitle = "Sitecore Web Developer";
                client.SetFacet(knownContact, PersonalInformation.DefaultFacetKey, personalInfoFacet);
                #endregion
                #region EmailAddress Facet
                EmailAddressList emails = new EmailAddressList(new EmailAddress("alok.kadudeshmukh@gmail.com", true), EmailAddressList.DefaultFacetKey);
                //OR the following code
                //var emails = existingContact.GetFacet(EmailAddressList.DefaultFacetKey);
                //emails.PreferredEmail = new EmailAddress("alok.kadudeshmukh@gmail.com", true);
                client.SetFacet(knownContact, EmailAddressList.DefaultFacetKey, emails);
                #endregion

                //Interaction
                var offlineGoal = Guid.Parse("A9948719-E6E4-46D2-909B-3680E724ECE9");//offline goal - KioskSubmission goal
                var channelId = Guid.Parse("3FC61BB8-0D9F-48C7-9BBD-D739DCBBE032"); // /sitecore/system/Marketing Control Panel/Taxonomies/Channel/Offline/Store/Enter store - offline enter storl channel
                //Create a new interaction for that contact
                Interaction interaction = new Interaction(knownContact, InteractionInitiator.Contact, channelId, "");
                // Add events - all interactions must have at least one event
                var xConnectEvent = new Goal(offlineGoal, DateTime.UtcNow);
                interaction.Events.Add(xConnectEvent);
                //Add interaction to client
                client.AddInteraction(interaction);

                client.Submit();
            }
        }

That’s it. Run the method and you can find the Contact added in the Expereince Profile.

Happy Coding 🙂

 

You can go back to previous step Step 5 – Facets or jump to the Main Page

Basics of xConnect – Step 5 – Create Facets

Facet is properties of the contact or interaction which adds some extra inforamtion about it. Like, name and address of the contact or the location of the interaction.

Facet contains,

  • Facet Model
  • Facet Definition (key)

There are two categories of facets:

  • Value facets
  • Calculated facets

Value facets can be set by using the xConnect Client API  from any client where as the Calculated facet are related to the contact’s interaction history, contact’s average engagement value per visit.

For more information regarding facets, have a look at https://doc.sitecore.net/developers/xp/xconnect/xconnect-model/facets/index.html

 

Let’s Create the Facet

                //Facets
                #region Personal Information Facet
                //Persona information facet
                PersonalInformation personalInfoFacet = new PersonalInformation();
                personalInfoFacet.Title = ddTitle.SelectedValue;
                personalInfoFacet.FirstName = "Alok";
                personalInfoFacet.MiddleName = "S";
                personalInfoFacet.LastName = "KaduDeshmukh";
                personalInfoFacet.PreferredLanguage = "en";
                personalInfoFacet.Gender = "Male";
                personalInfoFacet.JobTitle = "Sitecore Web Developer";
                client.SetFacet<PersonalInformation>(knownContact, PersonalInformation.DefaultFacetKey, personalInfoFacet);
                #endregion
                #region EmailAddress Facet
                EmailAddressList emails = new EmailAddressList(new EmailAddress("alok.kadudeshmukh@gmail.com", true), EmailAddressList.DefaultFacetKey);
                //OR the following code
                //var emails = existingContact.GetFacet<EmailAddressList>(EmailAddressList.DefaultFacetKey);
                //emails.PreferredEmail = new EmailAddress("alok.kadudeshmukh@gmail.com", true);
                client.SetFacet<EmailAddressList>(knownContact, EmailAddressList.DefaultFacetKey, emails);
                #endregion

Facet properties are quite self explanatory.

Now, the method createUpdateContact() would look like following:

        public void createUpdateContact()
        {
            //Certificate
            CertificateWebRequestHandlerModifierOptions options =
            CertificateWebRequestHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=587d948806e57cf511b37a447a2453a02dfd3686");
            var certificateModifier = new CertificateWebRequestHandlerModifier(options);

            //Model - xConnect Client Configuration
            List<IHttpClientModifier> clientModifiers = new List<IHttpClientModifier>();
            var timeoutClientModifier = new TimeoutHttpClientModifier(new TimeSpan(0, 0, 20));
            clientModifiers.Add(timeoutClientModifier);

            // This overload takes three client end points - collection, search, and configuration
            var collectionClient = new CollectionWebApiClient(new Uri("https://sc9.xconnect/odata"), clientModifiers, new[] { certificateModifier });
            var searchClient = new SearchWebApiClient(new Uri("https://sc9.xconnect/odata"), clientModifiers, new[] { certificateModifier });
            var configurationClient = new ConfigurationWebApiClient(new Uri("https://sc9.xconnect/configuration"), clientModifiers, new[] { certificateModifier });

            var config = new XConnectClientConfiguration(
                new XdbRuntimeModel(CollectionModel.Model), collectionClient, searchClient, configurationClient);
            //initialize the configuration
            config.Initialize();

            //create the xConnect Client
            using (Sitecore.XConnect.Client.XConnectClient client = new XConnectClient(config))
            {
                // Identifier
                var identifier = new ContactIdentifier[]
                {
                    new ContactIdentifier("HIxConnect", "contact.name@demo.com", ContactIdentifierType.Known)
                };

                //Contact & Facets
                // Create a new contact with the identifier
                Contact knownContact = new Contact(identifier);
                client.AddContact(knownContact);

                //Facets
                #region Personal Information Facet
                //Persona information facet
                PersonalInformation personalInfoFacet = new PersonalInformation();
                personalInfoFacet.Title = ddTitle.SelectedValue;
                personalInfoFacet.FirstName = "Alok";
                personalInfoFacet.MiddleName = "S";
                personalInfoFacet.LastName = "KaduDeshmukh";
                personalInfoFacet.PreferredLanguage = "en";
                personalInfoFacet.Gender = "Male";
                personalInfoFacet.JobTitle = "Sitecore Web Developer";
                client.SetFacet<PersonalInformation>(knownContact, PersonalInformation.DefaultFacetKey, personalInfoFacet);
                #endregion
                #region EmailAddress Facet
                EmailAddressList emails = new EmailAddressList(new EmailAddress("alok.kadudeshmukh@gmail.com", true), EmailAddressList.DefaultFacetKey);
                //OR the following code
                //var emails = existingContact.GetFacet<EmailAddressList>(EmailAddressList.DefaultFacetKey);
                //emails.PreferredEmail = new EmailAddress("alok.kadudeshmukh@gmail.com", true);
                client.SetFacet<EmailAddressList>(knownContact, EmailAddressList.DefaultFacetKey, emails);
                #endregion

                //Interaction
                client.Submit();
            }
        }

Let’s go to Next Step Step 6- Create Interaction

You can go back to previous step Step 4 – Contacts or jump to the Main Page

Basics of xConnect – Step 4 – Create Contacts

Before directly jumps to create Contact, let’s first understands the Contact.

A end user who interacts with the website/application is a contact.

Contact vs Sitecore User:

A contact and Sitecore user are two completely separate things. Sitecore user is a user who can access the CMS where as Contact is not having rights to use CMS by default. Contact is created in xDB.

Though, there is no implicit relationship between user & contact, developer can define such relationship explicitly. Developer can map the unique properties of both i.e. the username of Sitecore user and the identifier of the Contact.

Sitecore.XConnect.Contact class is used to create Contact object. Whenever this contact is created in xDB, ID has been assigned which is a GuID. Contacts should have atleast one identifier to identify it outside xDB.

Contacts are of Two types:

  • Known Contact – having known identifier
  • Anonymous Contact – having alias identifier.

Ref: https://doc.sitecore.net/developers/xp/xconnect/xconnect-model/contacts/

 

Let’s Create the Known Contact now,


                //Contact & Facets
                // Create a new contact with the identifier
                Contact knownContact = new Contact(identifier);
                client.AddContact(knownContact);

                //Facets

                //Interaction
                client.Submit();

Replace this code with the //Contact & Facets comment in the createUpdateContact() method.

//Contact & Facets

//Facets

//Interaction

So, now method should look like following:

        public void createUpdateContact()
        {
            //Certificate
            CertificateWebRequestHandlerModifierOptions options =
            CertificateWebRequestHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=587d948806e57cf511b37a447a2453a02dfd3686");
            var certificateModifier = new CertificateWebRequestHandlerModifier(options);

            //Model - xConnect Client Configuration
            List clientModifiers = new List();
            var timeoutClientModifier = new TimeoutHttpClientModifier(new TimeSpan(0, 0, 20));
            clientModifiers.Add(timeoutClientModifier);

            // This overload takes three client end points - collection, search, and configuration
            var collectionClient = new CollectionWebApiClient(new Uri("https://sc9.xconnect/odata"), clientModifiers, new[] { certificateModifier });
            var searchClient = new SearchWebApiClient(new Uri("https://sc9.xconnect/odata"), clientModifiers, new[] { certificateModifier });
            var configurationClient = new ConfigurationWebApiClient(new Uri("https://sc9.xconnect/configuration"), clientModifiers, new[] { certificateModifier });

            var config = new XConnectClientConfiguration(
                new XdbRuntimeModel(CollectionModel.Model), collectionClient, searchClient, configurationClient);
            //initialize the configuration
            config.Initialize();

            //create the xConnect Client
            using (Sitecore.XConnect.Client.XConnectClient client = new XConnectClient(config))
            {
                // Identifier
                var identifier = new ContactIdentifier[]
                {
                    new ContactIdentifier("HIxConnect", "contact.name@demo.com", ContactIdentifierType.Known)
                };

                //Contact & Facets
                // Create a new contact with the identifier
                Contact knownContact = new Contact(identifier);
                client.AddContact(knownContact);

                //Facets

                //Interaction
                client.Submit();
            }
        }

Let’s go to Next Step Step 5- Create Facets

You can go back to previous step Step 3 – Identifier or jump to the Main Page

Basics of xConnect – Step 3 – Create Identifier

ID can be used to identify the contact inside the xDB. But to identify the contact outside the xDB, you have to assign a identifier. Examples of valid identifiers include the website which the user is comming from, website logins, social media handles, referrals, etc.

Sitecore.XConnect.ContactIdentifier class can be used to initialize the Identifier.

Each Identifier consist of following:

An identifier Source, which describes where the identifier comes from – such as ‘twitter’ or might be the domain name of the website

An Identifier, such as a username or email id

An identifier ContactIdentifierType – either ContactIdentifierType.Anonymous  or ContactIdentifierType.Known

You can identify if the Contact is known or anonymous by using IsKnown property.

Contacts are uniquely identified by a combination of Identifier and Source. This requirement supports the following scenarios:

  1. A contact using the same username across multiple systems – for example, using myrtlesitecore on Twitter as well as Instagram
  2. Two different contacts using the same username – for example, contact 1 using sitecore on Instagram and contact 2 using sitecore on Twitter.

Let’s create identifier,

// Identifier
var identifier = new ContactIdentifier[]
{
    new ContactIdentifier("HIxConnect", "alok.kadudeshmukh@gmail.com", ContactIdentifierType.Known)
};

Paste this code in place of // Identifier &amp;amp;amp;amp; Contact

You can notice that it is an array ContactIdentifier[]. This is because a single contact can have multiple identifiers. A contact’s identifiers are represented by the Identifiers property on the Contact class.

The first parameter of the ContactIdentifier() is the Source – here I have kept it hardcoded domain name – “HIxConnect” (hardcoded domain name is not best practice. I have done it just because of demo purpose).

2nd parameter is the unique identifier string. Here I have used an email id.

3rd parameter is the type. Either ContactIdentifierType.Known or ContactIdentifierType.Anonymous.

 

So, now your method should look like following:

        public void createUpdateContact()
        {
            //Certificate
            CertificateWebRequestHandlerModifierOptions options =
            CertificateWebRequestHandlerModifierOptions.Parse("StoreName=My;StoreLocation=LocalMachine;FindType=FindByThumbprint;FindValue=587d948806e57cf511b37a447a2453a02dfd3686");
            var certificateModifier = new CertificateWebRequestHandlerModifier(options);

            //Model - xConnect Client Configuration
            List clientModifiers = new List();
            var timeoutClientModifier = new TimeoutHttpClientModifier(new TimeSpan(0, 0, 20));
            clientModifiers.Add(timeoutClientModifier);

            // This overload takes three client end points - collection, search, and configuration
            var collectionClient = new CollectionWebApiClient(new Uri("https://sc9.xconnect/odata"), clientModifiers, new[] { certificateModifier });
            var searchClient = new SearchWebApiClient(new Uri("https://sc9.xconnect/odata"), clientModifiers, new[] { certificateModifier });
            var configurationClient = new ConfigurationWebApiClient(new Uri("https://sc9.xconnect/configuration"), clientModifiers, new[] { certificateModifier });

            var config = new XConnectClientConfiguration(
                new XdbRuntimeModel(CollectionModel.Model), collectionClient, searchClient, configurationClient);
            //initialize the configuration
            config.Initialize();

            //create the xConnect Client
            using (Sitecore.XConnect.Client.XConnectClient client = new XConnectClient(config))
            {
                // Identifier
                var identifier = new ContactIdentifier[]
                {
                    new ContactIdentifier("HIxConnect", "contact.name@demo.com", ContactIdentifierType.Known)
                };

                //Contact & Facets

                // Interaction
            }

        }

Let’s go to Next Step Step 4- Create Contact

You can go back to previous step Step 2 – Model or jump to the Main Page