Iterating and calling custom functions for each record – AC Workflow

Many times we get stuck in situations where we have to perform a task for each record particularly when the default out-of-box functions provided by Adobe Campaign does not provide the required capability. The task could be anything like calling a third party or sending web request for each record with personalized data and capturing the responses from third party and back enriching our record set based on responses.  So, the ask is iterating through the records irrespective of targeting (Query, Read List, Union, Intersection, Split, Enrichment, Change dimension etc) and call that custom function for each record.

Another key important point to be taken care here, is the name of targeting schema itself which we have to iterate. The name could be generated dynamically or assigned on the run without being taken care of with proper naming convention. So, we need to do something flexible enough that it should not depend on the nomenclature of targeting schema.

Below are the basic steps that would help solving the problem here:

  1. Capturing the name of targeting schema that exists at previous step dynamically using variable vars.targetSchema.
    //Get the schema name (skipping namespace)
    var schemaName = vars.targetSchema.substring(vars.targetSchema.indexOf(":") + 1);
    

    The variable schemaName assigned above plays a critical role as it will be used in steps ahead while iterating the records.

  2. Querying the record set received from previous targeting.
    var datalayer = {
      get: {
        records: function( ) {
          var query = xtk.queryDef.create(  
            <queryDef schema={vars.targetSchema} operation="select">
              <select>
                <node alias="Id" expr="@Id"/>
                <node alias="Field1" expr="@Field1"/>
                <node alias="Field2" expr="@Field2"/>
                <node alias="Field3" expr="@Field3"/>
                <node alias="CreationDate" expr="@CreationDate"/>
              </select>
              <where>
                <condition expr={"@id IS NOT NULL"} />
              </where>
            </queryDef>
          ).ExecuteQuery();
    
          return query;
        }
      }
    }
  3. Iterating the records, calling custom function and recording the responses.
    var businessLogic = {
      createTempResponse : function(response, myResponseVariable){
        return {
                Id:response.Id,
                Field1:response.Field1,
                Field2:response.Field2,
                Field3: response.Field3,
                CreationDate: response.CreationDate,
                myVariable: myResponseVariable
              }
      },
      processResponses : function(records, schemaName){
        //Iterating through the record set here
        for each ( var record in records[schemaName] ) {
          
          myResponseVariable = myCustomFunction(record.Field1, record.Field2);
          datalayer.save( businessLogic.createTempResponse(record, myResponseVariable));
          
        }
      },
      //This is the custom function that calls third party or perform any specific functionality not available in AC
      myCustomFunction: function(field1, field2){
        
        //Add custom function code here that say returns a data stored in variable myResponseVariable
        return myResponseVariable;
      }
    }

    The method myCustomFunction() is the custom method which can be used to add custom behaviors. All the required parameters from targeting schema can be passed to this method and responses can be captured and stored in temprary table if required.
    The method processResponses() is iterating through the recordset and uses schemaName to fecth the value of each field in teh record.

  4. We can Save the result in a temporary table  and can later use it through enrichment to map back to targeting through primary key (@id in our case) and do further tasks in the workflow.
    var datalayer = {
      save: function ( data ) {
        //Save record to Temporary Table "TempResponses"
          xtk.session.Write(
            <TempResponses xtkschema="cus:TempResponses" _operation="insert" Id={data.Id}
              Field1={data.Field1}  Field2={data.Field2} Field3 = {data.Field3} CreationDate = {data.CreationDate}, Field4 = {data.myVariable} />);
         }
    }
  5. Now, the last part is to call the consolidate these bits and pieces and call them to make it work.
    var records = datalayer.get.records();
    
    businessLogic.processResponses(records, schemaName);

So, finally the whole code would look something like this:

//Get the schema name (skipping namespace)
var schemaName = vars.targetSchema.substring(vars.targetSchema.indexOf(":") + 1);

/*****************************************************************************************************/
var datalayer = {
  get: {
    records: function( ) {
      var query = xtk.queryDef.create(  
        <queryDef schema={vars.targetSchema} operation="select">
          <select>
            <node alias="Id" expr="@Id"/>
            <node alias="Field1" expr="@Field1"/>
            <node alias="Field2" expr="@Field2"/>
            <node alias="Field3" expr="@Field3"/>
            <node alias="CreationDate" expr="@CreationDate"/>
          </select>
          <where>
            <condition expr={"@id IS NOT NULL"} />
          </where>
        </queryDef>
      ).ExecuteQuery();

      return query;
    }
  }
  save: function ( data ) {
    //Save record to Temporary Table "TempResponses"
      xtk.session.Write(
        <TempResponses xtkschema="ahl:TempResponses" _operation="insert" Id={data.Id}
          Field1={data.Field1}  Field2={data.Field2} Field3 = {data.Field3} CreationDate = {data.CreationDate}, Field4 = {data.myVariable} />);
     }
}
/*****************************************************************************************************/

var businessLogic = {
  createTempResponse : function(response, myResponseVariable){
    return {
            Id:response.Id,
            Field1:response.Field1,
            Field2:response.Field2,
            Field3: response.Field3,
            CreationDate: response.CreationDate,
            myVariable: myResponseVariable
          }
  },
  processResponses : function(records, schemaName){
    //Iterating through the record set here
    for each ( var record in records[schemaName] ) {
      
      myResponseVariable = myCustomFunction(record.Field1, record.Field2);
      datalayer.save( businessLogic.createTempResponse(record, myResponseVariable));
      
    }
  },
  //This is the custom function that calls third party or perform any specific functionality not available in AC
  myCustomFunction: function(field1, field2){
    
    //Add custom function code here that say returns a data stored in variable myResponseVariable
    return myResponseVariable;
  }
}
/*****************************************************************************************************/

var records = datalayer.get.records();

businessLogic.processResponses(records, schemaName);

The workflow configuration for the use case is depicted as below:

Enjoy!!

(Visited 810 times, 2 visits today)