Optimizely and Chat GPT

Extending Optimizely CMS Text Property Editor with ChatGPT API Integration

By Aria Zanganeh
9 May 2023

ChatGPT is an AI language model developed by OpenAI that can generate human-like text based on a given input prompt. It can be used in various applications, such as content creation, question answering, or even code generation. The ChatGPT Complete API allows developers to integrate ChatGPT into their applications, enabling new ways to interact with the AI model.

In this blog post, we will discuss how to extend the Optimizely CMS Text Property Editor by adding a button that opens a popup where the editor can provide a prompt. The prompt will then be sent to the ChatGPT API, and the proposed content generated by ChatGPT will be returned to the editor.

ChatGPT Complete API

The ChatGPT Complete API is a RESTful API that provides access to ChatGPT’s text generation capabilities. It allows developers to send a prompt as input and receive generated content as output. The API can be accessed using an API key provided by OpenAI, and it supports various parameters to fine-tune the generated text, such as temperature and maximum tokens.

Extending CMS text property editor with API integration

1. Create a service for the ChatGPT API integration:

To start, create an IOpenAiService interface and an OpenAiService implementation class. This service will be responsible for sending requests to the ChatGPT API and returning the generated content. Don’t forget to replace the API key placeholder with your actual API key.

Here’s an example of the IOpenAiService interface and the OpenAiService class:

2. Create a controller to handle API calls from the front-end:

Next, create a ChatGptController class that will handle the communication between the front-end and your service. The controller will receive the prompt from the editor and call the GenerateText method from your service.

Example of the ChatGptController class:


public class ChatGptController : ControllerBase
      private readonly IOpenAiService openAiService;
      public ChatGptController(IOpenAiService openAiService)
           this.openAiService = openAiService;

      public async Task<string> Index(string prompt)
            return await openAiService.GenerateText(prompt);


3. Create custom property editor descriptor:

Create a custom EditorDescriptor for your new property editor. This descriptor will link the property editor with the front-end JavaScript control. Register your descriptor using the EditorDescriptorRegistration attribute.

Example of the custom EditorDescriptor:

[EditorDescriptorRegistration(TargetType = typeof(string), UIHint = Constants.ChatGptUIHint)]

public class ChatGptControlPropertyEditorDescriptor : EditorDescriptor {
      public override void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes) {
            base.ModifyMetadata(metadata, attributes);
            metadata.ClientEditingClass = "chatgpt-extension-control";


4. Create the front-end JavaScript control:

Create a custom JavaScript control that extends the Optimizely CMS Text Property Editor. This control will add the “Enrich Me!!!” button and handle the popup for prompting the editor. It will also communicate with your ChatGptController to call the ChatGPT API and display the generated content.

Example of the custom JavaScript control:

], function (
    ) {
    return declare("chatgpt-extension-control", [OriginalTextarea, _ValueRequiredMixin], {
        baseClass: "epi-textarea custom-textarea",
        _setValueAttr: function (value) {
        startup: function () {
            var button = domConstruct.create("button", { innerHTML: "Enrich Me!!!" });
            button.type = "button";
            button.style = "display: block; margin-bottom: 10px; background-color: white; color: #0037FF; padding: 8px 16px; border-radius: 4px; border: 1px solid #0037FF; cursor: pointer;";
            on(button, "click", this._onButtonClick.bind(this));
            var parent = this.domNode.parentNode;
            this.domNode.style = "width: 1000px; height: 800px;"
            parent.insertBefore(button, this.domNode);
        _updateUI: function () {
        _onButtonClick: function () {
            var self = this;
            var dialog = new Dialog({
                title: "Enter prompt",
                style: "width: 1000px; height: 800px;"

            var promptTextArea = new Textarea({
                value: "",
                style: "width: 100%; margin-bottom: 10px;"


            var responseTextArea = new Textarea({
                value: "",
                style: "width: 100%; height: 400px !important; margin-bottom: 10px;"


            var sendButton = new Button({
                label: "Send",
                onClick: function () {
                    sendButton.set("disabled", true);
                    var prompt = promptTextArea.get("value");
                    self._callApi(prompt, function (result) {
                        sendButton.set("disabled", false);
                        responseTextArea.set("value", result);


            var closeButton = new Button({
                label: "Close and Copy",
                onClick: function () {
                    var content = responseTextArea.get("value");

        _callApi: function (prompt, callback) {
            var self = this;
                url: "/api/ChatGpt?prompt=" + encodeURIComponent(prompt),
                content: { text: prompt },
                handleAs: "text",
                load: function (result) {

        _showLoader: function (show) {
            if (show) {
                var loader = document.createElement("div");
                loader.className = "loader";
                loader.style.cssText = "position: fixed; left: 0; top: 0; width: 100%; height: 100%; z-index: 9999; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center;";

                var spinner = document.createElement("div");
                spinner.className = "spinner";
                spinner.style.cssText = "border: 8px solid #f3f3f3; border-top: 8px solid #3498db; border-radius: 50%; width: 60px; height: 60px; animation: spin 2s linear infinite;";

                document.body.style.overflow = "hidden";
                loader.setAttribute("id", "loader");
            } else {
                var loader = document.getElementById("loader");

                if (loader) {
                    document.body.style.overflow = "auto";


5. Register the JavaScript control in the module.config file:

Finally, register your custom JavaScript control in the module.config file, so Optimizely CMS can load the control when needed.

        <add name="chatgpt-extension-control" path="Scripts/chatgpt-extension-control"/>


By following the steps above, you can extend the Optimizely CMS Text Property Editor with ChatGPT API integration. This will provide a seamless experience for content editors, allowing them to generate AI-powered content quickly and efficiently.