WS-Proxy via SSJS for SOAP API Object : Documentation

WS-Proxy via SSJS for SOAP API Object : Documentation
Home Page

WS-Proxy via SSJS: Documentation

Introduction:

Server-Side JavaScript (SSJS) is a powerful technology that allows developers to execute JavaScript code on the server-side, enabling them to build dynamic and scalable applications. The WSProxy object is native to the platform and simpler to use than the SSJS methods. The object reduces overhead and increases speed of your API calls. The object’s usage syntax is much more JavaScript-like when compared to the existing platform functions.In this blog post, we will explore how to leverage WS-Proxy, a Salesforce feature, to work with SOAP APIs using SSJS. We'll dive into the details of WS-Proxy and demonstrate how it can simplify and streamline SOAP API integrations.

Quote "The legacy methods for accessing SOAP object data, including what is used in the SSJS Core Library, are primarily wrappers around AMPScript functions. Using legacy SSJS methods adds overhead to the processing of the calls as the code translates the data between the different language runtimes." Unquote

What is WS-Proxy?

WS-Proxy is a server-side JavaScript utility provided by Salesforce that acts as a proxy for making SOAP API calls. It abstracts the complexity of SOAP requests and responses, providing a simplified interface for developers to interact with SOAP APIs. WS-Proxy is built on top of the AJAX toolkit, making it compatible with JavaScript Remoting, JavaScript buttons, and other client-side and server-side JavaScript contexts.

Benefits of WS-Proxy:

  1. Simplified Integration: WS-Proxy simplifies the integration process by abstracting the complexities of SOAP API calls. Developers don't need to worry about constructing SOAP envelopes, handling SOAP headers, or parsing SOAP responses. WS-Proxy takes care of these details, allowing developers to focus on the business logic.
  2. Security and Compliance: WS-Proxy ensures that the SOAP API calls are made securely, handling authentication and encryption behind the scenes. It adheres to Salesforce's security policies and ensures compliance with the organization's security settings.
  3. Performance Optimization: WS-Proxy optimizes the SOAP API calls by reducing the network overhead. It batches multiple API requests into a single network call, reducing latency and improving overall performance. This feature is particularly useful when working with bulk operations or when making multiple API calls in a single transaction.

Using WS-Proxy with SOAP API:

Let's dive into the practical implementation of WS-Proxy with a SOAP API integration. In this example, we'll demonstrate how to retrieve information from an external system using a SOAP API.

Step 1: Enabling WS-Proxy

To use WS-Proxy, you need to enable the "Allow server-side scripting for the service" option.


<script runat="server">
</script>
          

Step 2: Creating a WS-Proxy Script

Write a server-side JavaScript function that utilizes the WSProxy object provided by Salesforce. This object acts as a proxy for making SOAP API calls.


var api = new Script.Util.WSProxy();
          

Step 3: Making SOAP API Calls

In Salesforce Marketing Cloud, the ws-proxy or Web Services Proxy is a JavaScript library that allows you to invoke SOAP (Simple Object Access Protocol) web service methods, such as CreateItem and CreateBatch , from the client-side (browser) within the context of a Marketing Cloud CloudPage or other custom applications.

Step 4: Processing the Response

Once the SOAP response is received, you can process the data as needed. WS-Proxy handles the parsing of SOAP envelopes, making it easy to extract the relevant information from the response.

For example, the response contain three properties from the SOAP CreateResult object: “Status”, “RequestID”, and “Results”.


{
      "Status": "OK",
      "RequestID": "fb768ddc-6670-4183-8b9d-4f0d5518bb2e",
      "Results": [...]
}
            

Impersonation with WSProxy:

WSProxy introduces impersonation capabilities that allow developers to execute API requests on behalf of other users. This is accomplished by specifying the impersonated user's credentials within the WSProxy configuration. When a request is made using impersonation, the server treats the request as if it were made by the impersonated user, inheriting their privileges and access rights.

To impersonate another user, or switch contexts, use the setClientId method on the WSProxy object.You can add multiple credentials to a single WSProxy, but most actions use only the first one set as they accept only a single ClientId object.

api.setClientId({ "ID": 1234, "UserID": 1234 });

OR

api.setClientId({ "ID": 1234 });

OR

api.setClientId({ "ID": Platform.Function.AuthenticatedMemberID() });

OR

api.setClientId({ "UserID": 1234 });

You can retrieve User ID from AccountUser object as ID property.

var accountUser = AccountUser.Retrieve({Property:"CustomerKey",SimpleOperator:"equals",Value:"MyAccount"});

Impersonation only works with Top Down Approach, validate your Business Unit hierarchy when you are switching context between different operations.

To clear all set ClientId objects, use the resetClientIds() method. After using this method, the request goes back to using the default credentials determined by the execution context.

api.resetClientIds();

Methods:

Create via WSProxy

  1. createItem
  2. var res = api.createItem(soapObject,jsonObject,prop);
  3. createBatch
  4. var res = api.createBatch(soapObject,jsonArray,prop);
  • For the first parameter, both functions take the object type to perform the action on. For example, Email or DataExtension.
  • The second parameter is a JS object which represents the fields and values to set on the object when created. For batch operations, the second parameter is passed in as an Array of objects instead of a single item.
  • The third parameter is optional and includes any properties to be set using the SOAP CreateOptions object.

Update via WSProxy

  1. updateItem
  2. var res = api.updateItem(soapObject,jsonObject,prop);
  3. updateBatch
  4. var res = api.updateBatch(soapObject,jsonArray,prop);
  • For the first parameter, both functions take the object type to perform the action on. For example, Email or DataExtension.
  • The second parameter is a JS object which represents the fields and values to set on the object when created. For batch operations, the second parameter is passed in as an Array of objects instead of a single item.
  • The optional third parameter includes any properties to be set using the SOAP UpdateOptions object.

Delete via WSProxy

  1. deleteItem
  2. var res = api.deleteItem(soapObject,jsonObject,prop);
  3. deleteBatch
  4. var res = api.deleteBatch(soapObject,jsonArray,prop);
  • For the first parameter, both functions take the object type to perform the action on. For example, Email or DataExtension.
  • The second parameter is a JS object which represents the fields and values to set on the object when created. For batch operations, the second parameter is passed in as an Array of objects instead of a single item.
  • The optional third parameter includes any properties to be set using the SOAP DeleteOptions object.

Describe via WSProxy

To return information on the structure of SOAP API objects, use the describe call. The function takes either a string representing the object type to describe, or an array of strings for multiple object types.

Example :


 <script runat="server">
  Platform.Load("core", "1");
  try {
    var soapObjects=[
                       "Account"
                      ,"AccountUser"
                      ,"Authentication"
                      ,"Automation"
                      ,"BounceEvent"
                      ,"BusinessUnit"
                      ,"ClickEvent"
                      ,"ContentArea"
                      ,"DataExtension"
                      ,"DataFolder"
                      ,"Email"
                      ,"Send"
                      ,"SendClassification"
                   ]
    var response=DescribeSoapObject(soapObjects[12]);
    Write(Stringify(response));
  }
  catch (ex) {
    Write(ex.message + '\n');
    Write(ex.description + '\n');
    Write(ex.jintException + '\n');
  }

  function DescribeSoapObject(soapObjectname)
  {
    var api = new Script.Util.WSProxy();
    var response = api.describe(soapObjectname);
    return response;
  }
</script>               
            

Basic Retrieves via WSProxy

The WSProxy() object offers several retrieve options, depending on the level of complexity you need. The simplest option takes the type of object as the first parameter, and an array of object property names to retrieve.

Example :


<script runat="server">
  Platform.Load("core", "1");
  try {
    var soapObjects=[
                       "Account"
                      ,"AccountUser"
                      ,"Authentication"
                      ,"Automation"
                      ,"BounceEvent"
                      ,"BusinessUnit"
                      ,"ClickEvent"
                      ,"ContentArea"
                      ,"DataExtension"
                      ,"DataFolder"
                      ,"Email"
                      ,"Send"
                      ,"SendClassification"
                   ]
    var cols = [ "Name", "CustomerKey"];
    var response=RetrieveSoapObject(soapObjects[0],cols);
    Write(Stringify(response));
  }
  catch (ex) {
    Write(ex.message + '\n');
    Write(ex.description + '\n');
    Write(ex.jintException + '\n');
  }

  function RetrieveSoapObject(soapObjectname,cols )
  {
    var api = new Script.Util.WSProxy();
    var response = api.retrieve(soapObjectname,cols);
    return response;
  }
</script>
                

Example : Retrieve with Filter


<script runat="server">
  Platform.Load("core", "1");
  try {
    var soapObjects=[
                       "Account"
                      ,"AccountUser"
                      ,"Authentication"
                      ,"Automation"
                      ,"BounceEvent"
                      ,"BusinessUnit"
                      ,"ClickEvent"
                      ,"ContentArea"
                      ,"DataExtension"
                      ,"DataFolder"
                      ,"Email"
                      ,"Send"
                      ,"SendClassification"
                   ]
    var cols = [ "Name", "CustomerKey"];
    var filter=ApplyFilter("CustomerKey","equals","Shashi")
    var response=RetrieveSoapObject(soapObjects[0],cols,filter);
    Write(Stringify(response));
  }
  catch (ex) {
    Write(ex.message + '\n');
    Write(ex.description + '\n');
    Write(ex.jintException + '\n');
  }

  function RetrieveSoapObject(soapObjectname,cols,filter)
  {
    var api = new Script.Util.WSProxy();
    var response = api.retrieve(soapObjectname,cols,filter);
    return response;
  }

  function ApplyFilter(prop,operator,value)
  {
    return {
        Property: prop,
        SimpleOperator: operator,
        Value: value
    };
  }
</script>                  
                

Example : Retrieve with Complex Filter


<script runat="server">
  Platform.Load("core", "1");
  try {
    var soapObjects=[
                       "Account"
                      ,"AccountUser"
                      ,"Authentication"
                      ,"Automation"
                      ,"BounceEvent"
                      ,"BusinessUnit"
                      ,"ClickEvent"
                      ,"ContentArea"
                      ,"DataExtension"
                      ,"DataFolder"
                      ,"Email"
                      ,"Send"
                      ,"SendClassification"
                   ]
    var cols = [ "Name", "CustomerKey"];
    var leftOperand=ApplyFilter("CustomerKey","equals","Shashi");
    var rightOperand=ApplyFilter("Name","equals","Shashi");
    var filter=ComplexFilter(leftOperand,"OR",rightOperand)
    var response=RetrieveSoapObject(soapObjects[0],cols,filter);
    Write(Stringify(response));
  }
  catch (ex) {
    Write(ex.message + '\n');
    Write(ex.description + '\n');
    Write(ex.jintException + '\n');
  }

  function RetrieveSoapObject(soapObjectname,cols,filter)
  {
    var api = new Script.Util.WSProxy();
    var response = api.retrieve(soapObjectname,cols,filter);
    return response;
  }

  function ApplyFilter(prop,operator,value)
  {
    return {
        Property: prop,
        SimpleOperator: operator,
        Value: value
    };
  }

  function ComplexFilter(leftOperand,logicalOperator,rightOperand)
  {
    return {
        LeftOperand: leftOperand,
        LogicalOperator:logicalOperator,
        RightOperand: rightOperand
    };
  }
</script>
                

Example : Retrieve Data Extension from all Business Unit

This example uses a parameter called queryAllAccounts to retrieve data extension from all BUs, where CustomerKey OR Name is "Shashi"


<script runat="server">
  Platform.Load("core", "1");
  try {
    var soapObjects=[
                       "Account"
                      ,"AccountUser"
                      ,"Authentication"
                      ,"Automation"
                      ,"BounceEvent"
                      ,"BusinessUnit"
                      ,"ClickEvent"
                      ,"ContentArea"
                      ,"DataExtension"
                      ,"DataFolder"
                      ,"Email"
                      ,"Send"
                      ,"SendClassification"
                   ]
    var cols = [ "Name", "CustomerKey"];
    var leftOperand=ApplyFilter("CustomerKey","equals","Shashi");
    var rightOperand=ApplyFilter("Name","equals","Shashi");
    var filter=ComplexFilter(leftOperand,"OR",rightOperand);
    var queryAllAccounts = true;
    var response=RetrieveSoapObject(soapObjects[8],cols,filter,queryAllAccounts);
    Write(Stringify(response));
  }
  catch (ex) {
    Write(ex.message + '\n');
    Write(ex.description + '\n');
    Write(ex.jintException + '\n');
  }

  function RetrieveSoapObject(soapObjectname,cols,filter,queryAllAccounts)
  {
    var api = new Script.Util.WSProxy();
    var response = api.retrieve(soapObjectname,cols,filter,queryAllAccounts);
    return response;
  }

  function ApplyFilter(prop,operator,value)
  {
    return {
        Property: prop,
        SimpleOperator: operator,
        Value: value
    };
  }

  function ComplexFilter(leftOperand,logicalOperator,rightOperand)
  {
    return {
        LeftOperand: leftOperand,
        LogicalOperator:logicalOperator,
        RightOperand: rightOperand
    };
  }
</script>
                

Conclusion:

WS-Proxy provides an efficient and streamlined way to work with SOAP APIs using Server-Side JavaScript. By abstracting the complexities of SOAP requests and responses, developers can focus on building robust integrations without worrying about low-level SOAP details. The simplicity, security, and performance optimizations offered by WS-Proxy make it an excellent choice for integrating Salesforce with external systems using SOAP APIs. So, the next time you need to work with SOAP APIs in your Server-Side JavaScript applications, consider leveraging the power of WS-Proxy to simplify your integration process.

Share on Facebook Share on LinkedIn Share on WhatsApp

Comments


Knowledge Article

Most Viewed

CLOUD PAGE ENABLEMENT - PART 1

EMAIL NOT SENT IN JOURNEY BUILDER

CONSIDERATIONS FOR JOURNEY BUILDER

Journey Builder REST API Documentation

Preference Center Demystified

Popular Posts

CLOUD PAGE ENABLEMENT - PART 1

EMAIL NOT SENT IN JOURNEY BUILDER

CONSIDERATIONS FOR JOURNEY BUILDER

Journey Builder REST API Documentation

Preference Center Demystified

SEND LOG EANBLEMENT

Share with Friends

Disclaimer:

The information provided on this technical blog is for general informational purposes only. As a SFMC (Salesforce Marketing Cloud) Technical Architect, I strive to offer accurate and up-to-date content related to SFMC and its associated technologies. However, please note that technology is constantly evolving, and the information provided may become outdated or inaccurate over time.

The content published on this blog represents my personal views and experiences as a SFMC Technical Architect and does not necessarily reflect the official views or opinions of any organization or employer I may be affiliated with.

While I make every effort to ensure the accuracy and reliability of the information presented, I cannot guarantee its completeness, suitability, or applicability to your specific circumstances. Therefore, it is essential to verify any information provided and make your own independent assessments or seek professional advice if needed.

Furthermore, any actions taken based on the information provided on this blog are at your own risk. I shall not be held liable for any damages, losses, or inconveniences arising from the use of the information presented here.

Please keep in mind that SFMC and its associated technologies are complex and require technical expertise for proper implementation and management. It is recommended to consult with qualified professionals or official SFMC documentation for comprehensive guidance.

Finally, please note that any product or company names mentioned on this blog are trademarks or registered trademarks of their respective owners. The mention of these trademarks or registered trademarks does not imply any endorsement or affiliation with the blog.

By accessing and using this blog, you agree to the terms of this disclaimer. If you do not agree with any part of this disclaimer, please refrain from using this blog.