Author: sandeeppote

Gracefully handle user subscription using Sitecore Send

In this blog will walk you through on implementing subscribing and ubsubscribing user from the mail list using Sitecore Send

Use hostname- https://api.sitecoresend.io/v3

Subscribing a user to a mailing list

Api endpoint to subscribe a user to a mailing list

{hostname}/subscribers/{MailingListID}/subscribe.{Format}?apikey={apikey}

Subscribe Code

function SubscribeNewsletter(){

              let email = document.getElementById("newsletteremail");
              console.log(email)

              if (email.value == "") {
                alert("Ensure you input a value in both fields!");
              } else {
                // perform operation with form input
                
                var request = new XMLHttpRequest();
                request.open('POST', 'https://api.sitecoresend.io/v3/subscribers/{maillist}/subscribe.json?apikey={apikey}');
                request.setRequestHeader('Content-Type', 'application/json');
                request.setRequestHeader('Accept', 'application/json');
                request.onreadystatechange = function () {
                  if (this.readyState === 4) {
                    console.log('Status:', this.status);
                    console.log('Headers:', this.getAllResponseHeaders());
                    console.log('Body:', this.responseText);
                  }
                };
                var body = {
                  'Name': 'Sandeep Pote',
                  'Email': email.value,
                  'HasExternalDoubleOptIn': false
                };
                request.send(JSON.stringify(body));
                email.value = "";
                alert("User subscribed to newsletter")
              }
            };

Unsubscribe a user from a mailing list

Api endpoint to un-subscribe a user to a mailing list

{hostname}/subscribers/{MailingListID}/unsubscribe.{Format}?apikey={apikey}

Unsubscribe Code-

function UnSubscribeNewsletter(){

              let email = document.getElementById("optout-newsletteremail");
              console.log(email)

              if (email.value == "") {
                alert("Ensure you input a value in both fields!");
              } else {
                // perform operation with form input
                
                var request = new XMLHttpRequest();
                request.open('POST', 'https://api.sitecoresend.io/v3/subscribers/{maillist}/unsubscribe.json?apikey={apikey}');
                request.setRequestHeader('Content-Type', 'application/json');
                request.setRequestHeader('Accept', 'application/json');
                request.onreadystatechange = function () {
                  if (this.readyState === 4) {
                    console.log('Status:', this.status);
                    console.log('Headers:', this.getAllResponseHeaders());
                    console.log('Body:', this.responseText);
                  }
                };
                var body = {
                    'Email': email.value,                  
                };
                request.send(JSON.stringify(body));
                email.value = "";
                alert("User subscribed to newsletter")
              }
              };

Looks simple, but you might see when the user un-subscribed from a mailing list the user is never sent a mail from other mailing list or any other transactional mail.

Set user to unsubscribe from a specific mailing list

To allow only to unsubscribe from the a specific mailing list update a Unsubscribe setting-

For this goto Settings –> Set your account settings in Sitecore Send and check the Unsubscribe settings

Select option- When unsubscribing users from a list send to them from other mailing lists

Now the user will be only unsubscribed from the specific mailing list and sending mails from the Other mailing list of capaign should be possible.

This setting is very important whilst working with Sitecore send.

Reference-

https://doc.sitecore.com/send/en/developers/api-documentation/add-a-new-subscriber.html

https://doc.sitecore.com/send/en/developers/api-documentation/unsubscribe-a-subscriber-from-a-mailing-list.html

Loading

Sitecore CDP – Abandon cart with force close event

You can force close event to test Abandon Cart. This works only in non-prod environments.

Assumption- An identified guest which is active and has added products in cart.

If you are corectly tracking you should see in the timeline Session and event a Product been added.

So whilst developing if you want to force close this session, since you might not want to wait for 20 minutes for session to expire or whatever time is set to expire the session, you can force close the session to see or perform the next steps if the cart is been abandoned.

The force close event can be triggered by providing message type as FORCE_CLOSE in the payload.

Send the payload to this endpoint. For more details on what should be the apiEndpoint and client key see this blog

https://{{apiEndpoint}}/{{apiVersion}}/event/create.json?client_key={{CLIENT_KEY}}&message={{message}}

var browser_id = pm.environment.get("browserId") -- browser id
var pointOfSale = pm.environment.get("PointOfSale") -- point of sale

var message = {    
    "channel": "WEB",
    "type": "FORCE_CLOSE",
    "language": "EN",
    "currency": "GBP",
    "page": "home page",
    "pos": pointOfSale,
    "browser_id": browser_id
}

postman.setEnvironmentVariable("message", JSON.stringify(message));

Since the session is now closed we can see the Abandoned Revenue. Further reminder mails can be sent to user to complete the purchase on the abandoned cart.

Hope this helps.

Loading

Sitecore CDP – Upload guest data

Prepare guest data file to upload

Prepare Json file

Take a sample guest data from here

Sample data guest looks like this-

{
   "ref":"b4b92667-54e9-444f-8f64-11672fe9843a",
   "schema":"guest",
   "mode":"upsert",
   "value":{
      "guestType":"customer",
      "firstSeen":"2010-03-07T16:15:11.000Z",
      "lastSeen":"2012-08-23T16:17:16.000Z",
      "firstName": "Eager",
      "lastName": "Benz",
      "email": "eager.benz@malify.com",
      "extensions":[
         {
            "name":"ext",
            "key":"default",
            "loyaltytier":"level2",
            "rewardBalance":"50125"            
         }
      ]
   }
}
{
   "ref":"0cc6c80b-0b19-446f-9e14-579f75a96c4a",
   "schema":"guest",
   "mode":"upsert",
   "value":{
      "guestType":"customer",
      "firstSeen":"2010-03-07T16:15:11.000Z",
      "lastSeen":"2012-08-23T16:17:16.000Z",
      "firstName": "Goofy",
      "lastName": "Trovalds",
      "email": "goofy.trovalds@malify.com",
      "extensions":[
         {
            "name":"ext",
            "key":"default",
            "loyaltytier":"level3",
            "rewardBalance":"50130"            
         }
      ]
   }
}

Load the data in json file. Note that the above is a single row in a json and repeat the rows to upload multiple guets. This is not a json formatted file and should not have “,” to seperate rows as normally json file has. Highlighted email is important to identify the customer and add/update the extended data. This depends on the rule setup for your environment to identify the customer.

gzip the json file to upload

Example-

tar -czvf guest-upload.gz .\guest-upload.json

Generate MD5 File Checksum

Upload the gzip file to generate the check sum on this url –

https://emn178.github.io/online-tools/md5_checksum.html

Prepare Pre-signed Request

Create a new guid for the below batch upload. This guid will be used to know the status of the batch upload.

https://api.boxever.com/v2/batches/<<your guid>>

Request body –

{
    "checksum": "aaab5899b405bc3cb1d9b*******",
    "size": 412
}

Setup the Basic Auth before sending the request-

Request after setting up Authentication and body-

Response-

location – where the file needs to be uploaded. Will see this is next request where we actually upload file.

expiry – date time until the location to upload file is valid

The response should be saved in environment with uploadURL and batchRef variable-

Upload file

Upload URL request should contain the URL received from the pre-signed request-

Set the headers-

x-amz-server-side-encryption – AES256

Content-Md5 – <<Hex to Base checksum value>>

Content-Md5 is the Hex to Base64 converted value of checksum

Use this url to convert to base64-

https://base64.guru/converter/encode/hex

Request Headers should look like this-

The request signature we calculated does not match the signature you provided. Check your key and signing method.

Send request to the provided URL with the attached gzip file and headers. Response 200 Ok

Check the status of the uploaded file-

https://api.boxever.com/v2/batches/{{batchRef}}

The upload is queued and may take time depending on the items queued.

With the below request it shows the upload request is processing.

This request took almost 2 hours to complete, and the response here is error where 1 of the guets is updated but opther failed.

This is the log, where you should be able to rectify any errors in json file-

Lets check the other guest if available in portal-

Errors

SignatureDoesNotMatch

Loading

Send Abandoned Cart email using Sitecore Send Automation

Sitecore Send lets you automate your communication with customers by identifying specific situations that trigger the sending of an email message

In this blog lets create automated mails using automation recipes.

For more details see this link.

Pre-requisite-

Ensure the website is configured and verified before using the automation. See this blog. For this blog post I am using – https://moosend.vercel.app/

Create automation using Abandoned Cart automation recipe

Navigate to Automation link and create new automation using recipe-

Select Abandoned cart recipes-

Will be shown the Abandoned Cart Workflow-

Choose Trigger option-

Select- Trigger every time option

Select your website from dropdown and Save. Only verified website will be visible here. You may also choose all sites.

Open wait operation-

For testing I have selected 5 minutes. Ideally this can be few hours/days as per the requirement or enter specific date. By default it is 45 minutes. Enter the wait time and Save.

Setup the filter

Select apply this filter to mailing list. I have selected the email list of the site, you may select different list.

Enter the product if you wish to or leave empty.

Click on “Add a collection”.

Select the time if the product is not purchased for certain time. I have entered 6 minutes. Enter the details and Save.

Select “Added a Product To Cart” and filter value. In this I have added product “Americano”.

Select timer and enter the wait time to 6 minutes and Save

Select the action

In this case Send the mail to user if the product is not purchased in selected time.

Select Send Mail campaign-

Enter the subject, From address, mail body. Select Emails per day. Save once this option is filled.

Activate the “Abandoned Cart” automation-

Automation List with activated

Once the automation configuration is complete will now add product to cart. the product name here is “Americano” as selected in filter.

In the installation script you can find the details on how to add the product to cart.

function addToCart(){
                // mandatory - a unique code for the product, like its SKU
                    var itemCode = 'Americano';
                    // mandatory - the name / title of this product
                    var itemName = 'Iced Americano';
                    // mandatory - the image url of this product
                    var itemImage = 'http://your.store/product-color-blue.jpg';
                    // mandatory - the price of this product
                    var itemPrice = 10.25;
                    // mandatory - the url to get to the relevant product page
                    var itemUrl = 'http://your.store/product-101';
                    // mandatory
                    var itemQuantity = 1;
                    // mandatory - the total price for purchasing the given quantity of this product
                    var itemTotalPrice = 10.25;
                    // optional - the category of this product
                    var itemCategory = 'Drinks';
                    // optional - the manufacturer, brand name or company / owner of this product (if any)
                    var itemManufacturer = 'Acme Co';
                    // optional - the supplier of this product (if any)
                    var itemSupplier = 'Supplier Co';

                    // you can add custom properies and later use them in segmentations or automations
                    // You can track things like the color or the sze of the t-shirt in this case
                    var extraProps = {'flavor': 'Chocolate', 'type': 'Iced'};

                    // Tracking add to cart events with mandatory arguments
                    mootrack('trackAddToOrder', itemCode, itemPrice, itemUrl, itemQuantity, itemTotalPrice);

                alert("Added to cart event fired");
}

Hook the Add to cart to button-

<button class="button" onclick="addToCart()">Add to cart</button>

The site looks like this with the “Add To Cart” button

Website confirm the event was triggered.

In the automation list you can see the automation been Triggerd-

Once this is triggered you can see the next operation Wait for 5 minutes-

A mail should be triggerd after 6 minutes. Since the product is still in cart and not purchased.

After 5 minutes all the actions should be triggered.

Once all the actions are triggered should receive the mail-

Thats it for this blog. We have managed to trigger a automation event and send themail to the users who have product in the cart and not purchased e.e. Abandoned Cart.

Loading

Run Bitcoin full test node in Linux

This installation is performed on freshly installed Ubuntu system.

sudo apt update
snap install bitcoin-core

This should install Bitcoin Core on Ubuntu machine-

But lets not use GUI for this and setup test node using Bitcoin Daemon.

Bitcoin daemon should be installed in root folder and the executable can be found on this path- /snap/bitcoin-core/141/bin

Use below command to find the version of the daemon-

bitcoin-core.daemon --version

Run command –

bitcoin-core.daemon

Here the last line its expecting a bitcoin.conf file in location- /home/sandy/snap/bitcoin-core/common/.bitcoin/bitcoin.conf. This oath might be different for you.

Create a bitcoin.conf file at this location and paste in following to configure bitcoin daemon to run in test node.

Set the chain=test

set path to blocksdir and datadir

set txindex=1 to index the transaction

Set rpcuser and rpcpassword to use JSON rpc api

server=1 tells Bitcoin-QT to accept JSON-RPC commands.

# [chain]
# Test Network.
chain=test

# [core]
# Specify a non-default location to store blockchain data.
blocksdir=/home/sandy/snap/bitcoin-core/common/.bitcoin
# Specify a non-default location to store blockchain and other data.
datadir=/home/sandy/snap/bitcoin-core/common/.bitcoin

# Options only for mainnet
[main]

# Options only for testnet
[test]

# Options only for regtest
[regtest]

txindex=1

server=1

rpcuser=your_rpc_user
rpcpassword=your_rpc_pwd

rpcallowip=*

-txindex
Maintain a full transaction index, used by the getrawtransaction rpc
call (default: 0)

-rpcpassword=
Password for JSON-RPC connections

-rpcuser=
Username for JSON-RPC connections

Run following command to run the daemon in test node. This will download the data which is around 29gb at the time of writing this blog.

bitcoin-core.daemon -txindex -rpcuser=your_rpc_user -rpcpassword=your_rpc_pwd

This should now start the daemon and will check if the data is available, if not this should start download the blocks.

First it wll pre-Synchronize the block headers and then start Synchronizing headers. At the time of writing this blog there are around 2428000 blocks in test node.

Once synchronizing is complete it should start downloading and indexing blocks-

2023-07-23T15:14:46Z UpdateTip: new best=0000000000002f4ee789f0bd19066bccd78172ca71995505996fbff1a3341eac height=271984 version=0x00000002 log2_work=60.719797 tx=2107245 date=’2014-08-05T09:37:28Z’ progress=0.031835 cache=337.4MiB(2518207txo)

Here the height is the block it has synchronised and the progress. When the progress is near to 1 it will come to completion of synchronising the node.

In the above example 0000000000002f4ee789f0bd19066bccd78172ca71995505996fbff1a3341eac is a block hash

progress when near to 1 means it about to complete synchronising all blocks.

A new folder called testnet3 will be created in .bitcoin folder – This should be in user folder and not root folder.

For me it took less than 2 hours to sync all blocks.

2023-07-23T16:55:23Z UpdateTip: new best=0000000000000022020dfc2655e4489eb54a8ae306080a47d1fa0be46e0c43a8 height=2443382 version=0x31636000 log2_work=75.416383 tx=66092181 date='2023-07-23T16:40:35Z' progress=0.999999 cache=479.2MiB(3458766txo)
2023-07-23T16:56:04Z New outbound peer connected: version: 70015, blocks=2443382, peer=76 (block-relay-only)
2023-07-23T17:00:42Z Saw new header hash=0000000000001019c41ee044adf1c02d347ed52d875eefeb8e629f0a5baa4a8b height=2443383
2023-07-23T17:00:42Z [net] Saw new cmpctblock header hash=0000000000001019c41ee044adf1c02d347ed52d875eefeb8e629f0a5baa4a8b peer=3
2023-07-23T17:00:42Z UpdateTip: new best=0000000000001019c41ee044adf1c02d347ed52d875eefeb8e629f0a5baa4a8b height=2443383 version=0x29e7a000 log2_work=75.416383 tx=66092225 date='2023-07-23T17:00:37Z' progress=1.000000 cache=479.2MiB(3458790txo)

The last block to sync was 2443382

It also listens to any new block been created on chain- 2443383 which happened after 5 minutes. See highlighted.

Quick check-

Pick the block – 2443383

bitcoin-core.cli -rpcuser=xxxx -rpcpassword=xxxxx getblockhash 2443382

It should print the hash-

0000000000000022020dfc2655e4489eb54a8ae306080a47d1fa0be46e0c43a8

Take this hash and use command to get block

bitcoin-core.cli -rpcuser=xxxxxx -rpcpassword=xxxxx getblock 0000000000000022020dfc2655e4489eb54a8ae306080a47d1fa0be46e0c43a8

Output – should show details of the block along with the transactions- I have trimmed the transactions here due to space.

{
  "hash": "0000000000000022020dfc2655e4489eb54a8ae306080a47d1fa0be46e0c43a8",
  "confirmations": 2,
  "height": 2443382,
  "version": 828596224,
  "versionHex": "31636000",
  "merkleroot": "9e0403fef59a803426851f3c428306c15d81360f665f37cc62549825056c6823",
  "time": 1690130435,
  "mediantime": 1690129060,
  "nonce": 2392034863,
  "bits": "192495f8",
  "difficulty": 117392538.8721802,
  "chainwork": "000000000000000000000000000000000000000000000aad36ccc3b8310b4b65",
  "nTx": 26,
  "previousblockhash": "000000000000000b994cbbfe015d77aaa70140af817b6d28d228da690d1ce4da",
  "nextblockhash": "0000000000001019c41ee044adf1c02d347ed52d875eefeb8e629f0a5baa4a8b",
  "strippedsize": 5511,
  "size": 8258,
  "weight": 24791,
  "tx": [
    "b96a95b85e2ec270b471afded7d49c7db46d5002ac43de0bbcc13a4dd972f763",
    "823f5a59b5c6878ba68f21fdfdc9fe796fc879a471d69fcd0430200d9e5aba9a",
    
  ]
}

GetRawTransactions

bitcoin-core.cli -rpcuser=xxxx -rpcpassword=xxxxx getrawtransaction b96a95b85e2ec270b471afded7d49c7db46d5002ac43de0bbcc13a4dd972f763

Output-

010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff1e0376482519444d47426c6f636b636861696e309e3c095f01000000000000ffffffff02b29a270000000000160014b23716e183ba0949c55d6cac21a3e94176eed1120000000000000000266a24aa21a9eddcc8960d06c43b2eaab1e03370081155bac04c26ea7282b8dffaf7c2c452d2220120000000000000000000000000000000000000000000000000000000000000000000000000

This confirms that the blocks are indexed as the getrawtransaction looks for node and not your own wallet transaction.

How to get transaction details will put that in another blog.

Hope this helps to configure full test node on your system.

Performance

To run the daemon blockonly option – 

bitcoind -daemon -blocksonly

.By default, bitcoind relays transactions while you’re syncing and using -blocksonly turns that off. It probably won’t make a huge difference but should save you some bandwidth. 

Increase dbcache

-dbcache= The default for this is 450. If you have 8GB of RAM, you could set this to 4096

Enable website tracking service using Sitecore Send

Sitecore Send website tracking service enables to collect data and makes it available for users. It uses cookie-based technology to track data on end-user page visits, product view, add to cart and purchase.

Add website to Sitecore Send

Pre-requisite-

You need to have a website up and running. this can be a simple HTML site or you can choose any other web techology with any Fronetend framework like nextjs, react or jquery etc.

I have created a simple site and hosted using vercel – e.g.:- https://moosend.vercel.app/

To add a website to Sitecore Send –

Navigate to Account –> Websites or New Website option

List of Websites-

Should display list of Websites already configured and if its verified.

Add Website-

On this page enter your website url- https://moosend.vercel.app/

Once this is submitted it should show the Website Id alond with Connection Script. Website Id is required to add this in script to start tracking.

The website list should show the newly added website which should be in unverfied state-

Connect Website

Navigate to Install connection script option. Install button should show the script that is require to add to your website

Copy this script to you website head section, this may be different for you site –

mootrack('init', '77d7daa0-b906-4965-be85-7d8a8892019f');

The Id in the above code is website id.

Identify the visitor

To verify your site and to track the visitor use this script-

mootrack('identify', 'john@doe.com');

The above email will be identified.

Add script to you Website-

Add the above script in your website Head section, something like this-

The initila script which allows to use the mootrack fucntion with various options.

The mootrack init along with you website id

Local function to track user. I have hooked this function to a button

<button class="button" onclick="trackuser()">Track User</button>

Deploy the site to vercel-

I have deployed the site to vercel but you can choose your own hosting provider or the way you want to deploy the site.

My site looks like this and have button to “Track User”, “Add to cart” and “Checkout”

Click on “Track User” button, it should confirm the tracking.

This should also add cookie entry with user email-

And now you should see the website in Sitecore send should be in Verified state-

A new Email List will be created and a subscriber should have been added-

This concludes enabling the Sitecore Send for your website.

Errors

If you see this warning the site might not be tracking correctly due to cookie conflict. Delete all cookies before starting the tracking.

Loading

Sicore CDP – Send Add Event using direct HTTP request

The ADD event captures the product details when a user adds the product(s) to their online cart.

https://{{apiEndpoint}}/{{apiVersion}}/event/create.json?client_key={{CLIENT_KEY}}&message={{message}}

To know more what should be the API endpoint and api version see this blog

Pre-requisite- The guest has to be created which can be identitfied as browserid

Generate browser id – see how to generate browserid using postman here

URL – contains event to create Add event. – highlighted below.

Add the Product details the user must have added in cart and send the below request to Sitecore CDP.

At this point the Guest must have been identified as the Customer. Search Customer by browserid or Name.

Should the current activity of the customer.

Click on Timeline and View Session details

The session should show the product been added to the cart. Based on this if the product remains in cart for certain time and the user doen’t checkout you may provision to trigger abandon cart event.

cURL code snippet-

curl --location -g --request GET 'https://api.boxever.com/v1.2/event/create.json?client_key=<<Client Key>>&message={"channel":"WEB","type":"CONFIRM","language":"EN","currency":"GBP","page":"home page","pos":"pastoral-witty-grill","browser_id":"7ed103bd-08c2-47f4-8f69-91141ca3200d","product":[{"item_id":"EXACT_90"}]}'

C# code snippet-

var client = new RestClient("https://api.boxever.com/v1.2/event/create.json?client_key=<<Client Key>>&message={\"channel\":\"WEB\",\"type\":\"CONFIRM\",\"language\":\"EN\",\"currency\":\"GBP\",\"page\":\"home page\",\"pos\":\"pastoral-witty-grill\",\"browser_id\":\"7ed103bd-08c2-47f4-8f69-91141ca3200d\",\"product\":[{\"item_id\":\"EXACT_90\"}]}");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

Python code snippet-

import http.client

conn = http.client.HTTPSConnection("api.boxever.com")
payload = ''
headers = {}
conn.request("GET", "/v1.2/event/create.json?client_key=<<Client Key>>&message=%7B%22channel%22:%22WEB%22,%22type%22:%22CONFIRM%22,%22language%22:%22EN%22,%22currency%22:%22GBP%22,%22page%22:%22home%20page%22,%22pos%22:%22pastoral-witty-grill%22,%22browser_id%22:%227ed103bd-08c2-47f4-8f69-91141ca3200d%22,%22product%22:%5B%7B%22item_id%22:%22EXACT_90%22%7D%5D%7D", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

Reference-

https://doc.sitecore.com/cdp/en/developers/api/index-en.html#UUID-51cdc30a-8344-72dc-457c-98aa2866da39

Loading

Sitecore CDP – Send Identity Event using direct HTTP request

An IDENTITY event contains data that enables Sitecore CDP to perform identity resolution. When Sitecore CDP receives an IDENTITY event, it runs a linking algorithm to try to match guest data from separate guest profiles, based on your organization’s identity rules. 

A guest is identified with the browser id. To search the guest Navigate to the Guest list page and search for the guest with the browwser id.

To identify the guest as a Customer provide the payload with the type as IDENTITY and the Customer details, such as their email, firstname, lastname etc.

Sending a request through postman- use below URL-

https://{{apiEndpoint}}/{{apiVersion}}/event/create.json?client_key={{CLIENT_KEY}}&message={{message}}

To know more what should be the API endpoint and api version see this blog

Pre-requisite- The guest has to be created which can be identitfied as browserid

Generate browser id – see how to generate browserid using postman here

URL – contains event to create view event.

To know more about the point of sale and how to create see blog

var browser_id = pm.environment.get("browserId")
var pointOfSale = pm.environment.get("PointOfSale")

var message = {    
    "channel": "WEB",
    "type": "IDENTITY",
    "language": "EN",
    "currency": "GBP",
    "page": "Login",
    "pos": pointOfSale,
    "browser_id": browser_id,
    "title": "Sir",
    "email": "pgrill@malify.com",
    "firstname": "Patoral",
    "lastname": "Grill"
}

postman.setEnvironmentVariable("message", JSON.stringify(message));

Now search the Guest by browserid and the Gust Type should be Customer as the Guest has been identified.

CURL code snippet-

curl --location -g --request GET 'https://api.boxever.com/v1.2/event/create.json?client_key=<<client key>>&message={"channel":"WEB","type":"IDENTITY","language":"EN","currency":"GBP","page":"home page","pos":"pastoral-witty-grill","browser_id":"7ed103bd-08c2-47f4-8f69-91141ca3200d","title":"Sir","email":"pgrill@malify.com","firstname":"Pastoral","lastname":"Grill"}'

C# code snippet-

var client = new RestClient("https://api.boxever.com/v1.2/event/create.json?client_key=<<code key>>&message={\"channel\":\"WEB\",\"type\":\"IDENTITY\",\"language\":\"EN\",\"currency\":\"GBP\",\"page\":\"home page\",\"pos\":\"pastoral-witty-grill\",\"browser_id\":\"7ed103bd-08c2-47f4-8f69-91141ca3200d\",\"title\":\"Sir\",\"email\":\"pgrill@malify.com\",\"firstname\":\"Pastoral\",\"lastname\":\"Grill\"}");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

Python code cnippet-

import http.client

conn = http.client.HTTPSConnection("api.boxever.com")
payload = ''
headers = {}
conn.request("GET", "/v1.2/event/create.json?client_key=<<client key>>&message=%7B%22channel%22:%22WEB%22,%22type%22:%22IDENTITY%22,%22language%22:%22EN%22,%22currency%22:%22GBP%22,%22page%22:%22home%20page%22,%22pos%22:%22pastoral-witty-grill%22,%22browser_id%22:%227ed103bd-08c2-47f4-8f69-91141ca3200d%22,%22title%22:%22Sir%22,%22email%22:%22pgrill@malify.com%22,%22firstname%22:%22Pastoral%22,%22lastname%22:%22Grill%22%7D", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

References-

https://doc.sitecore.com/cdp/en/developers/api/index-en.html#UUID-279a4b64-8bb2-2e5d-3ec7-6b469e284dc7

Loading

Setting up a Sitecore JSS development environment with the Containers template for Next.js

Follow steps in this link —

https://doc.sitecore.com/xp/en/developers/hd/211/sitecore-headless-development/walkthrough–setting-up-a-development-environment-with-the-sitecore-containers-template-for-next-js.html

Following are thre pre-requisite for setting on your local machine-

Apart from this also install Sitecore JSS CLI-

npm install -g @sitecore-jss/sitecore-jss-cli

Install the template

dotnet new -i Sitecore.DevEx.Templates --nuget-source https://sitecore.myget.org/F/sc-packages/api/v3/index.json

dotnet new sitecore.nextjs.gettingstarted -n samplejss

Should first Restores dotnet local tools for the solution and Initializes the JSS project

What is your Sitecore hostname (used if deployed to Sitecore)? (samplejss.dev.local) << leave blank or provide the host name>>

How would you like to fetch Layout and Dictionary data? 
GraphQL
REST

How would you like to prerender your application?
SSG
SSR

Which additional language do you want to support (en is already included and required)? << leave blank or type the language you want. should select da-DK by default and additional language>>

JSS application is now ready and updated for continerized environment.

Navigate to project folder and initialize the environment.

.\init.ps1 -InitEnv -LicenseXmlPath "<C:\path\to\license.xml>" -AdminPassword "<desired password>"
setx NODE_EXTRA_CA_CERTS C:\Users\sandeep\AppData\Local\mkcert\rootCA.pem

Execute up.ps1 to create containers-

.\up.ps1

Error-

CM is not coming up-

Checked the docker logs, and found this error-

The path is not set correctly. Need to escape the characters-

Resolution-

Change – entrypoint: powershell.exe -Command “& C:\tools\entrypoints\iis\Development.ps1” to entrypoint: powershell.exe -Command “& C:\\tools\\entrypoints\\iis\\Development.ps1” in docker-compose.override.yml file for xm1, xp0 and xp1

Take down all the containers and build again.

Now this should look fine-

Enter CM admin credentials and allow the access-

CM and App should load –

As of writing this post, this setup installed Sitecore 10.3.

Loading