Splitting up a large workflow using External Signal

alistairk161838

16-03-2017

Hi,

I have a large complicated workflow which runs at the end of each campaign which summarises findings and then emails this to stakeholders.

Ideally I want to split this into two parts, the simply delivery part and the complicated summarisation part. The simple part will allow the operators to select their data and delivery templates and send the email. The complicated part does a ton of analysis work and delivers some files. The operators should never touch any of the complicated part.

I was thinking to put a signal at the end of the simple part which after X amount of time will trigger the complicated part, passing through the required variables to enable it to determine the campaign it needs to analyse and deliver the automated reports for.

How best to do this? I looked at signals and I think this is the best way, however I'm unsure of exactly how to trigger a signal from a workflow. 

 

Appreciate your input!

Accepted Solutions (1)

Accepted Solutions (1)

Vapsy

Employee

16-03-2017

Hi Alistair,

Signal seems to best suit your requirement. 

Each signal activity has an internal name and this is something which helps trigger the signal.

So at the end of simple part you can put a JS code activity.

Use the following code

xtk.workflow.PostEvent('Identifier or internal name of the workflow which contains signal activity', 'The name of the activity from which the event starts', 'The name of the transition to activate. If this name is empty, the event will be issued on the first valid transition', 'The parameters of the event in the form of an XML element. The name of the element must be variables.', 0)

Hope this helps.

Regards,

Vipul

Answers (21)

Answers (21)

Vapsy

Employee

11-10-2018

Hi LeonieSwart,

You will not be able to pass temp schema reference by an external signal.

The only option is to make use of sub-workflow.

Worth starting a new thread for your issue row work with Adobe Support

Regards,
Vipul

Adhiyan

Employee

03-07-2017

Hello Richa,

The split will be based on what you consider to be responders (open/clicks) for email1

Taking email clicks as responders for example , you can create a workflow like this

1>. External signal from previous workflow

2>. Query activity targeting the recipients of the delivery EMAIL1

3>. Split activity connected to the query with Generate complement option selected from the general tab . On the Subsets tab click on "add a filtering condition to the inbound population , click on Edit and select the filtering dimension as a temporary schema and select the query result as source.

Then add a filtering condition like shown in the screenshot here : TrackingLogRcp exists such as url/@type=email-click.forum1.JPG

4>. Add the subset to the SMS delivery and add the complement to the Email2 to send SMS to responders and email2 to non-responders.

Hope this helps.

Regards,

Adhiyan

Vapsy

Employee

16-03-2017

alistairk16183831 wrote...

Hi Vipul,

Would you be so kind as to show an actual example where a variable (such as a delivery Id) is being passed through?

 

Thanks!

 

Hi Alistair,

Hope this helps.

xtk.workflow.PostEvent('calledWorkflow','signal','', <variables varName= {vars.myName} />,false)

Regards,

Vipul

LeonieSwart

10-10-2018

Hi Vipul

I have an extra question about the external signal activity.

Does it pass along the temp schema data as well?

For example:

     In the main workflow:

          1) start activity

          2) query to select all recipients with language EN

          3) js activity to initiate call for the external signal

     In the flow with external signal

          1) the external signal is triggered by the main workflow

          2) add a split activity to divide target from main workflow into 2 groups

For me this isn't working as it seems that it doesn't know the temp schema from the main workflow.

Is there a way around?

I also tried this using a sub-workflow with an input transition of nms:recipients but the output of the sub-workflow isn't returning the schema as expected and is throwing errors. So I'm not sure if that is a better alternative.

Thank you for the information!

Kind regards

Leonie

richam007

03-07-2017

Hi,

Can you please help me with the following scenario:

I need to create an Engagement Split for an email. Engagers of Email 1 get mobile alert while non-engagers of Email 1 get Email 2.

Cab you please guide me how to implement this scenario in workflow?

Thanks,

Richa

alistairk161838

23-03-2017

Hi Vipul,

That's all fine thanks. I actually used my brain and solved it :). I did have another question on how best to interrogate the received split array but I've put together an inelegant solution which does the trick.

Appreciate all your help.

Vapsy

Employee

22-03-2017

alistairk39680404 wrote...

Hi Vipul,

The first part of the problem is the circular logic in this piece of code.

  1. {
  2. commaSeparatedDeliveryIds = commaSeparatedDeliveryIds + row.@id + ","; //Generate comma separated list of deliveryIds
  3. }

The commaSeperatedDeliveryIds variable is being used to define itself when it doesn't actually contain any info yet, therefore always returns 'undefined'. It also doesn't comma between itself and row.id. For example it returns 'undefined4242971,4241831'. If you move the commaSeperatedDeliveryIds variable about in the code then the 'undefined' value moves around too.
 

 

Hi Alistair,

The variable commaSeparatedDeliveryIds is initially undefined and hence the keyword is getting appended with your deliveryIds.

When defining the variable we can initialize it 

var commaSeparatedDeliveryIds = "";

This will fix the problem.

For the workflow id problem, as stated above you can use instance.id directly. I believe you have already figured it out on the related thread.

Please let me know if you have any queries.

Regards,

Vipul

alistairk396804

20-03-2017

Hi Vipul,

The first part of the problem is the circular logic in this piece of code.

{ commaSeparatedDeliveryIds = commaSeparatedDeliveryIds + row.@id + ","; //Generate comma separated list of deliveryIds }

The commaSeperatedDeliveryIds variable is being used to define itself when it doesn't actually contain any info yet, therefore always returns 'undefined'. It also doesn't comma between itself and row.id. For example it returns 'undefined4242971,4241831'. If you move the commaSeperatedDeliveryIds variable about in the code then the 'undefined' value moves around too.
 

alistairk396804

20-03-2017

Hi Vipul,

Thanks for your pointers on amending the bits of code. As I'm sure you are not surprised by I have a couple of questions;

Amending the 'Winner' JS script. I think I may have got this backwards?

// link the delivery to the operation to make sure it will be displayed in // the campaign dashboard. This attribute needs to be set manually here since // the Duplicate() method has reset it to its default value => 0 delivery.operation_id = winner.@["operation-id"] delivery.workflow_id = winner.@["instance-id"]

Concatenating the delivery ids.The updated code you supplied displays this (I'm displaying the final output with the end comma removed) so this appears to be working (I assume the lack of the delivery ID from the winning delivery is causing the undefined/lack of comma result).

Ignore my previous split questions - user error. I was overwriting [1] with [2].

I really do appreciate your help on this!

Vapsy

Employee

18-03-2017

Hi Alistair,

There are few missing points and hence you are facing this issue.

  1. The Campaign documentation explaining the script for selecting winner delivery just duplicates one of the A or B delivery and assigns the operation-id to it. In other words, the winner delivery is only being linked with the campaign.You'll have to add another line to this code so that attribute [@workflow-id] is populated with instance.id and then it will get picked by your queryDef.
  2. In you script towards the build up to PostEvent, when you are looping through the deliveryIds, it is required to develop a comma separated string of deliveryIds there itself. At present, it is not being done and hence only the last delivery is being passed to signal. Following code
    var resultSet = query.ExecuteQuery(); for each (var row in resultSet) { vars.myVar = row.@id; logInfo(vars.myVar); }
      should be changed to 
    var resultSet = query.ExecuteQuery(); var commaSeparatedDeliveryIds; for each (var row in resultSet) { commaSeparatedDeliveryIds = commaSeparatedDeliveryIds + row.@id + ","; //Generate comma separated list of deliveryIds logInfo(commaSeparatedDeliveryIds); } vars.myVar = commaSeparatedDeliveryIds.replace(/,\s*$/, ""); //Replace last comma and trailing whitespaces with blankspace

     

alistairk161838

17-03-2017

Hi Vipul,

Thanks for your patience here. That code is working (apart from one thing I will mention at the end);

// Define Delivery Variable var query = xtk.queryDef.create( <queryDef schema="nms:delivery" operation="select"> <select> <node expr="@id"/> </select> <where> <condition expr={"[@workflow-id]=" + instance.id}/> </where> </queryDef>); var resultSet = query.ExecuteQuery(); for each (var row in resultSet) { vars.myVar = row.@id; logInfo(vars.myVar); } //Pass through Variable xtk.workflow.PostEvent('WKF129','signal','', <variables varName= {vars.myVar} />,false)

It logs the following two Delivery IDs. These are correct.

 

In my signal workflow I have the JS script;

//  Split Variable var myArray = vars.varName.split(','); //  Define in vars vars.delId1 = myArray[0]; vars.delId2 = myArray[1]; vars.delId2 = myArray[2]; //  logInfo(vars.varName); logInfo(vars.delId1); logInfo(vars.delId2); logInfo(vars.delId3);

This logs the following delivery ID variables;

As you can see it takes only a single value instead of the two listed in the previous logs.

At what point are the delivery IDs parsed into a comma separated string? If I log the vars.varName variable it only has a single Delivery ID in it - the value I'm placing into vars.del1.

 

Final thing to mention, as you may remember my test workflow consisted of an AB test and a winning delivery, so I would expect to see three Delivery IDs, instead there only seem to be two present. The winning Delivery is not being picked up with that script. I suspect this is due to the way it is being generated and that perhaps it is not correctly assigning itself to this workflow. The script used for this winning Delivery is taken from the Adobe Campaign Use Case documentation. Would it be possible to take a look and see if this is the case?

Vapsy

Employee

17-03-2017

Hi Alistair,

Made a small mistake, forgot the @ symbol

Use this as expression for where clause

expr={"[@workflow-id]=" + instance.id}

Split is a JS fundtion which will take string like this as input1 "deliveryid1,deliveryid2,deliveryid3" and a delimiter as input 2 i.e. ','

It will output an array [deliveryid1, deliveryid2, deliveryid3]

You can then loop through this array to perform your logic.

This link should help http://stackoverflow.com/questions/3245088/how-to-split-a-comma-separated-string-and-process-in-a-lo...

Regards,

Vipul

Vapsy

Employee

17-03-2017

It is unable to understand attribute workflow-id in delivery schema. Please check the name of foreign key link to xtk:workflow and use that here. It will work then

Vapsy

Employee

17-03-2017

Split is a function part of JavaScript language. You will find a lot of examples on the internet.

As I don't have my laptop, can check the expression next week.

Vapsy

Employee

17-03-2017

Yes you are close. Just that the loop will generate multiple deliveryids you can create a comma separated  string and pass that in PostEvent. In the called workflow perform a JS split function to regenerate the deliveryids from passed variable.

The where clause will be expr={"[workflow-id]=" + instance.id}

Hope this helps 

alistairk161838

17-03-2017

Something along these lines (although my where clause is currently failing);

// Define Delivery Variable var query = xtk.queryDef.create( <queryDef schema="nms:delivery" operation="select"> <select> <node expr="@id"/> </select> <where> <condition expr=[workflow-id] = instance.id/> </where> </queryDef>); var resultSet = query.ExecuteQuery(); for each (var row in resultSet) { vars.myVar = row.@id; logInfo(vars.myVar); } //Pass through Variable xtk.workflow.PostEvent('WKF129','signal','', <variables varName= {vars.myVar} />,false)

Vapsy

Employee

17-03-2017

Hi Alistair, why not use queryDef inside end activity. Get all deliveries associated with current workflow by querying on nms:delivery where [workflow-id] = instance.id

alistairk161838

17-03-2017

This is working for a single delivery so thank you for those details!

My final requirement is for a multi delivery campaign such as an AB Test.

This is the code;

// Define Delivery Variable vars.myVar = vars.deliveryId; //Pass through Variable xtk.workflow.PostEvent('WKF129','signal','', <variables varName= {vars.myVar} />,false)

And this is the delivery scenario (code is in the END icon);

The above code only brings through a single delivery ID whereas I would need it to bring through all three. Furthermore I would want to devise a way to scale this up - so if an operator decides to do an ABCD test they can just add in the extra deliveries and not have to worry about additional variables.

Vapsy

Employee

17-03-2017

alistairk16183831 wrote...

That looks really good Vipul, I'll test that today. One final question from my head before I am able to test - lets say this was the variable I was creating;

  1. vars.myVar = instance.vars.deliveryId

and there were three records each with a different delivery ID in the data at that point, would all three be passed through to the signal?

 

Hi Alistair,

I'm not sure if I understood it correctly. If the requirement is to pass three deliveryIds in one go through signal you can do something like this.

vars.deliveryid1 = instance.vars.deliveryId1; vars.deliveryid2 = instance.vars.deliveryId2; vars.deliveryid3 = instance.vars.deliveryId3; xtk.workflow.PostEvent('calledWorkflow','signal','', <variables varName1= {vars.deliveryid1} varName2= {vars.deliveryid2} varName3= {vars.deliveryid3} />,false)

Hope this helps.

Regards,

Vipul