Exploring Sitecore Connect

If you have not read my series of blog posts on how I connected Sitecore SaaS products and chat gpt for a hackathon use case, you can start below and follow along.

Now, after I was done with the use case implementation as I mentioned on my last blog post here, I started thinking can I use Sitecore Connect as my data connection instead of chat gpt directly. I wanted to experiment and I was actually successful, lets see how.

I created a different decisioning model on Personalize instance for this very purpose

It is pretty simple because all logic for it will be on Sitecore connect this time around. It would look like this

Programmable here is just reading from our event data that we pushed originally and add geo data to the same. You can read about this on my blog post here

Data system here points to a new data connection created that is essentially pointing to webhook created on Sitecore Connect. It would look something like below

This is how the webhook is configured on Sitecore Connect in recipes

what this hook does is reads the prompt that is read/passed on Personalize data connection, sends that to open AI and then updates the guest on CDP with output from chat gpt.

Do note that UpdateGuest is a custom step I had added though it was very simple and does not have anything crazy in there

Action Name: UpdateGuest
Method: POST
Path: /v2/guests/Guestref Step 1/extext -> GuestRef is dynamic from step 1 payload which has guest reference ID that is needed to update guest on CDP and is unique identifier.
Request Type: JSON Request Body
Response Type: JSON Response


For this flow to work, connections should be in place for both Open AI and CDP account on which user will get updated. This was simple when all information needed is on hand. For instance, for CDP below are needed:
Region
Client Key
API Token
You can get these from CDP, developer settings once you are logged in

For open AI, you will need API key and that is it!

When you start the recipe and fire off the variant that would fire off decisioning path noted above, the whole flow should work and you should see that on CDP the guest is updated with the output from chat GPT. Of course, this is not perfect, but, this proves that low code/no code is possible!

Configure Data System for Chat GPT connection

I started this series in attempt to share how I connected Sitecore Cloud Platforms with Chat GPT. You can read all the pieces on my blog here below:

First Post
Second Post
Third post

This post covers one specific aspect that I started talking about in my third post. I will expound little more so you can easily configure a data system in your Sitecore CDP/Personalize platforms.

To configure data system in Sitecore Personalize as a connection there are few pre-requisites to keep handy. In our case it would be:

  • Request URL for chat gpt completion call based on prompt
  • Request Body format
  • Dynamic Request body values that can be passed from Decisioning flow

Lets see how we set this all up.

Go to Developer Center, select connections and select Data system as an option. There are other options for data systems and find out more about these options in Sitecore documentation here. Managing data systems in Sitecore Personalize | Sitecore Documentation

Follow the stepped form and pass all request related information noted above and once the connection is ready and saved it should look like below.

You can see the dynamic request body parameter that is needed to run the call when you click on test canvas.

This input parameter will be the prompt that is generated by programmable. If the test is successful, we are now ready now to wire this up on our decisioning as data system. A quick snapshot of how this data system is configured in Decisioning.

The request input named ‘ai prompt’ is read from programmable on the same decisioning canvas and is fed as input via arrow on canvas.

output references noted here can be useful, if these are used on next steps on canvas for instance. May be this prompt might need more massaging or may have to connect to another data system or decision matrix before it is read as response. In our POC case, we are ready. Now, lets run the canvas and examine output from chat gpt in this case for the guest ID of concern.

Full Response from test canvas for guest ID that visited the landing page via email looks like below

{
  "decisionModelName": "vodka byte offer links",
  "decisionModelRef": "2995976a-0984-4486-ad92-62d6715de27e",
  "decisionModelVariantName": "vb variant 3",
  "decisionModelVariantRef": "d3afe77c-3ff6-4797-8864-2e799c2ad5d1",
  "decisionModelVariantRevision": 3,
  "error": false,
  "debug": {
    "bucket": "0",
    "logs": ""
  },
  "decisionModelResultNodes": [
    {
      "id": "c9c3b6fe-2c3d-4304-bced-4f72cfb4d03c",
      "name": "Programmable 1",
      "error": false,
      "type": "programmable",
      "executionTime": 2.977723,
      "dependentNodeIds": [],
      "outputs": [
        {
          "programmable1": "Find a link to a Toyota dealership located in or near Cypress,US"
        }
      ]
    },
    {
      "id": "b81fbc2b-90a5-4fa4-b58f-cbfdfc9b1183",
      "name": "Vodka Byte Final",
      "error": false,
      "type": "connection",
      "executionTime": 392.346452,
      "dependentNodeIds": [
        "c9c3b6fe-2c3d-4304-bced-4f72cfb4d03c"
      ],
      "outputs": [
        {
          "vodkaByteFinal": {
            "created": 1692469327,
            "usage": {
              "prompt_tokens": 15,
              "completion_tokens": 15,
              "total_tokens": 30
            },
            "warning": "This model version is deprecated. Migrate before January 4, 2024 to avoid disruption of service. Learn more https://platform.openai.com/docs/deprecations",
            "model": "text-davinci-003",
            "id": "cmpl-7pKsJtZpSJk3FBXAlPYtRv4fJi8iT",
            "choices": [
              {
                "text": "\n\nhttp://www.toyotaofcypress.com/",
                "index": 0,
                "finish_reason": "stop"
              }
            ],
            "object": "text_completion"
          }
        }
      ],
      "connectionData": {
        "statusCode": 200,
        "executionTimeInMilliseconds": 392,
        "request": {
          "headers": {
            "Authorization": "Bearer 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",
            "Accept": "application/json",
            "X-Correlation-Id": "62f94b35-2f90-48c5-ba3f-b025941c9055",
            "Accept-Encoding": "gzip",
            "Content-Type": "application/json"
          },
          "body": {
            "model": "text-davinci-003",
            "max_tokens": 250,
            "temperature": 0.7,
            "prompt": "${aiprompt}"
          }
        },
        "response": {
          "headers": {
            "Date": [
              "Sat, 19 Aug 2023 18:22:07 GMT"
            ],
            "Content-Type": [
              "application/json"
            ],
            "Transfer-Encoding": [
              "chunked"
            ],
            "Connection": [
              "keep-alive"
            ],
            "access-control-allow-origin": [
              "*"
            ],
            "Cache-Control": [
              "no-cache, must-revalidate"
            ],
            "openai-model": [
              "text-davinci-003"
            ],
            "openai-organization": [
              "verndale"
            ],
            "openai-processing-ms": [
              "285"
            ],
            "openai-version": [
              "2020-10-01"
            ],
            "strict-transport-security": [
              "max-age=15724800; includeSubDomains"
            ],
            "x-ratelimit-limit-requests": [
              "3000"
            ],
            "x-ratelimit-limit-tokens": [
              "250000"
            ],
            "x-ratelimit-limit-tokens_usage_based": [
              "250000"
            ],
            "x-ratelimit-remaining-requests": [
              "2999"
            ],
            "x-ratelimit-remaining-tokens": [
              "249750"
            ],
            "x-ratelimit-remaining-tokens_usage_based": [
              "249750"
            ],
            "x-ratelimit-reset-requests": [
              "20ms"
            ],
            "x-ratelimit-reset-tokens": [
              "60ms"
            ],
            "x-ratelimit-reset-tokens_usage_based": [
              "60ms"
            ],
            "x-request-id": [
              "fdb61fe91425cfcac81fad751352504c"
            ],
            "CF-Cache-Status": [
              "DYNAMIC"
            ],
            "Server": [
              "cloudflare"
            ],
            "CF-RAY": [
              "7f946b8eca6a81d3-IAD"
            ],
            "alt-svc": [
              "h3=\":443\"; ma=86400"
            ],
            "Content-Length": [
              "-1"
            ]
          },
          "body": {
            "warning": "This model version is deprecated. Migrate before January 4, 2024 to avoid disruption of service. Learn more https://platform.openai.com/docs/deprecations",
            "id": "cmpl-7pKsJtZpSJk3FBXAlPYtRv4fJi8iT",
            "object": "text_completion",
            "created": 1692469327,
            "model": "text-davinci-003",
            "choices": [
              {
                "text": "\n\nhttp://www.toyotaofcypress.com/",
                "index": 0,
                "finish_reason": "stop"
              }
            ],
            "usage": {
              "prompt_tokens": 15,
              "completion_tokens": 15,
              "total_tokens": 30
            }
          },
          "statusCode": 200
        },
        "connectionUrl": "https://api.openai.com/v1/completions",
        "connectionRef": "d2c654e2-c873-4ee1-a0f9-bf92afeee3bd"
      }
    }
  ]
}

If you closely examine the outputs section, it has response from chat gpt that carries the link which we will then wire up on experience. Lets take a peek on how to do that

Complete the Variant

In Personalize, variant has advanced edit capabilities. In that, there is API tab can be leveraged to read information from response noted above from decision model that runs. quick glance of flow of web experience.

In our case, we needed to read the output from chatgpt as noted from decision canvas massage the same in API tab which can then be leveraged on HTML tab. Do note that in javascript tab, we were also able to send more events if the end user interacts with the CTAs in the pop up.

Personalize has preview option to test and ensure the experience looks as planned. Once it is up to expectations, this experiment can be made live. You can see below now that our experiment is live.

Below is how a whole event stack would look like, lets say if user clicks on our dynamically generated CTA for instance.

That is it!! Web experiment will now capture analytics which will help marketing team make decisions or create more variants leveraging data systems for ease of creation.

Now for the cliff hanger, can we do this using Sitecore Connect instead of using data connection? I thought to myself, I should and I was able to. Next post will be achieving what I did with Data systems using Sitecore Connect instead.

Deliver Personalized Experiences

If you have not read my first two blogs on this series of combining two awesome platforms to deliver a personalized experiences, you should start there. Below are the links to the same. This post is the third step of the series that talks about how we can use Personalize to tie everything together.

How it all started!
CDP to capture events

Now, lets roll!

This is step is all about key functionality of Sitecore Personalize such as web experiments, variants, decisioning and data connections. Lets start getting in to each step here:

  • Create a web experiment – This is not mandatory, one can also choose experiences, but, we wanted to prove some theories on analytics front, so, we used this. You can read more on how to do this straight in Sitecore documentation.
  • Add POS filter based on what was sent to CDP. More info on sitecore documentation here as well.
  • Now, create a decisioning model that has a programmable to read what was sent on custom events from CDP. Have input as Guest and sessions both so we can read what we need on programmable. Also, connect to Data system, in our case it is chat gpt/open AI. I will talk about how to set that up in next post. Below is how the decisioning would look like. Learn how to set them up from Sitecore documentation.

Programmable is a javascript snippet here is used to construct prompt that will then be passed to Data system (Chat GPT) as completion call input. It extracts below information

  • Custom Event extension data that is added when end user clicks on Landing page link on their email
  • Current Session data extension that carries geo information on user such as city and country.

Code on programmable looks like below. No, it is not production quality code as I did this for hackathon. 🙂 Please make sure yours is though. LOL

function getLastButtonClickEventText() {
    var lastButtonClickedText  = '';
    
    for (var i = 0; i < guest.sessions.length; i++) {
        var currentSession = guest.sessions[i];
        
        if (currentSession.sessionType === 'WEB') {
            var events = currentSession.events;
             var geoCity = currentSession.dataExtensions[0].values.geoLocationCity;
             var geoCountry =  currentSession.dataExtensions[0].values.geoLocationCountry;
             
            for (var j = 0; j < events.length; j++) {
                var currentEvent = events[j];

                if (currentEvent.type === 'vodkabyte:CLICKED_HERO_CTA' && currentEvent.arbitraryData && currentEvent.arbitraryData.ext.PersonalizationPrompt) {
                    lastButtonClickedText = currentEvent.arbitraryData.ext.PersonalizationPrompt+" "+ geoCity +"," + geoCountry ;
                    break;
                }
            }
        }

        if (lastButtonClickedText) {
            break;
        }
    }

    return lastButtonClickedText;
}

(function () {
  // Add statements here
  
 var lastButtonClickEvent = getLastButtonClickEventText();

    return lastButtonClickEvent;
  
})();

Custom event information is available inside the events on the session and looks like below

Next step is to feed this programmable data in to data system. But, first, we have to learn how to set that up. I will talk about that in my next post. Hang tight!