Optimizer API - Documentation

In order to use the Optimizer API, your Salesforce Org needs to have API usage activated through having an API usage license as well as having the finance module activated with the finance license.

The Optimizer API is implemented as Apex class and is exposed as REST web service by using Salesforce standard functionality (see Apex Developer Guide for more information). For general information about the Optimizer feature, see 4.11 Optimizer . The Create Optimization functionality compares the given Campaign Items to the existing Campaign Items from the database and creates an Optimizer Version containing all the changes/differences.

Please note that this API does not create the optimizing version record in your instance. To create the necessary records please take a look at the official Salesforce documentation about the creation of records via API: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_composite_sobject_tree_create.htm .
At least it will be needed to set the ADvendio__Source__c field of the ADvendio__OptimizingVersion__c record and the ADvendio__OptimizingVersion__c field of the ADvendio__OptimizingChange__c records which got returned by the API (as already visible in the example code at the bottom of the page).

1. REST web service

1.1. URL

https://<my-domain-name>.my.salesforce.com/services/apexrest/ADvendio/ADvendio__Campaign_Item__c/CreateOptimization/

1.2. Method

PATCH

1.3. URL Params

1.4. Data Params

A JSON object with the attribute campaignItems, containing a JSON serialized list of Campaign Items.

Example: { "campaignItems":[{<Campaign Item>}, ...]}

1.5. Success Response

Code: 200

Content: A JSON serialised Optimization (ADvendio__OptimizingVersion__c) record including all Optimizer Changes (ADvendio__OptimizingChange__c)

1.6. Error Response

See Salesforce Apex REST Documentation

1.7. Logic

When creating an Optimization, the Optimizer will create an Optimizing Change record for every single changed field. Optimizing Change contains a reference to the original Campaign Item, the old value, the new value and the developer name of the field.

Special cases:

  • related lists: When changing data, that is stored in related lists (Content, Targeting Sets), the old and new values contain a comma separated list of record ids.

  • new positions: When adding new Campaign Items during the optimization process, we need to store all (required/set) fields of the Campaign Item. Since there is no existing version of that Campaign Item but we have a master-detail relationship, the Optimizer uses a random Campaign Item Id from the same Media Campaign for the Campaign Item field. In the field ADvendio__NewCiIdentifier__c a dummy Id is saved to be able to identify what change belongs to what Campaign Item in case of adding more than one Campaign Item.

Please note that this API does not create the optimizing version record in your instance. To create the necessary records please take a look at the official Salesforce documentation about the creation of records via API: https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_composite_sobject_tree_create.htm .
At least it will be needed to set the ADvendio__Source__c field of the ADvendio__OptimizingVersion__c record and the ADvendio__OptimizingVersion__c field of the ADvendio__OptimizingChange__c records which got returned by the API (as already visible in the example code at the bottom of the page).

Pseudo code for creating the changes. This should help to collect the data for the insert via salesforce rest api:

for (campaignItem : optimizedCampaignItems) {
	for (field : creatableCampaignItemFields) {
		changes.add(new OptimizingChange__c(
			CampaignItem__c = campaignItem.isNew() ? IdFromAnyCampaignItemFromTheSameMc : originalCampaignItem['Id'],
			NewCiIdentifier__c = campaignItem.isNew() ? campaignItem['Id'] : null,
			FieldName__c = field,
			OptimizedValue__c = campaignItem[field],
			OriginalValue__c = originalCampaignItem[field]
		));
	}
	changes.addAll(createChangesForSpecialTargeting());
}

1.8. Examples

1.8.1. Get a Session-ID

curl -v https://login.salesforce.com/services/oauth2/token -d "grant_type=password" -d "client_id=<CLIENT_ID>" -d "client_secret=<CLIENT_SECRET>" -d "username=<USER_NAME>" -d "password=<PASSWORD+TOKEN>" -H 'X-PrettyPrint:1'


Get CLIENT_ID and CLIENT_SECRET from any connected app or create a new app in your org: App Manager -> New Connected App

1.8.2. Simple request

A simple request with a Campaign Item to change the Quantity from 1000 to 2000.

1.8.2.1. Call Optimizer web service

curl https://<my-domain-name>.my.salesforce.com/services/apexrest/ADvendio/ADvendio__Campaign_Item__c/CreateOptimization/ -H 'Authorization: Bearer <SESSION_ID>' -H "Content-Type: application/json" -H 'X-PrettyPrint:1' -d @requestBody.txt --request PATCH

1.8.2.2.
requestBody.txt

{
	"campaignItems":[
		{
			"Id":"a0HA000000SNYF4MAP",
			"ADvendio__Quantity__c":2000
		}
	]
}

1.8.2.3.
Response

[
  {
    "attributes":{
      "type":"ADvendio__OptimizingVersion__c",
      "Name":"2_30.07.2020",
      "ADvendio__MediaCampaign__c":"a1E2K00000KEBpOUAX",
      "CurrencyIsoCode":"EUR",
      "ADvendio__OptimizingChanges__r":{
        "totalSize":1,
        "done":true,
        "records":[
          {
            "attributes":{
              "type":"ADvendio__OptimizingChange__c","url":"/services/data/v49.0/sobjects/ADvendio__OptimizingChange__c/a1H2K00000iD0q8UAC"
            },
            "ADvendio__CampaignItem__c":"a0Y2K00000Fe82gUAB",
            "ADvendio__FieldName__c":"advendio__quantity__c",
            "ADvendio__OriginalValue__c":"1000.00",
            "ADvendio__OptimizedValue__c":"2000.00",
            "CurrencyIsoCode":"EUR"
          }
        ]
      }
    }
  ]

1.8.3.
Cancel an existing Campaign Item example

1.8.3.1. Call Optimizer web service

curl https://<my-domain-name>.my.salesforce.com/services/apexrest/ADvendio/ADvendio__Campaign_Item__c/CreateOptimization/ -H 'Authorization: Bearer <SESSION_ID>' -H "Content-Type: application/json" -H 'X-PrettyPrint:1' -d @requestBody.txt --request PATCH

1.8.3.2. requestBody.txt

{
  "campaignItems":[
    {
    "ADvendio__Media_Campaign__c":"a1E2K00000LnfyCUAR",
    "Id":"a0Y2K00000EsFaSUAV",
    "ADvendio__Quantity__c":0,
    "ADvendio__BillingStatus__c":"canceled"
        }
    ]
}

1.8.3.3. Response

{
    "attributes": {
        "type": "ADvendio__OptimizingVersion__c"
    },
    "ADvendio__MediaCampaign__c": "a1E2K00000LnfyCUAR",
    "ADvendio__OptimizingChanges__r": {
        "totalSize": 2,
        "done": true,
        "records": [
            {
                "attributes": {
                    "type": "ADvendio__OptimizingChange__c"
                },
                "ADvendio__CampaignItem__c": "a0Y2K00000EsFaSUAV",
                "ADvendio__FieldName__c": "advendio__quantity__c",
                "ADvendio__OptimizedValue__c": "0.0",
                "ADvendio__OriginalValue__c": "1.00",
                "CurrencyIsoCode": "EUR"
            },
            {
                "attributes": {
                    "type": "ADvendio__OptimizingChange__c"
                },
                "ADvendio__CampaignItem__c": "a0Y2K00000EsFaSUAV",
                "ADvendio__FieldName__c": "advendio__billingstatus__c",
                "ADvendio__OptimizedValue__c": "canceled",
                "ADvendio__OriginalValue__c": "created",
                "CurrencyIsoCode": "EUR"
            }
        ]
    },
    "CurrencyIsoCode": "EUR",
    "Name": "164_13.10.2020"
}

1.8.4. Add a new Campaign Item example

A simple request to add a new Campaign Item. There has to be an existing Media Campaign with at least one Campaign Item.

1.8.4.1. Call Optimizer web service

curl https://<my-domain-name>.my.salesforce.com/services/apexrest/ADvendio/ADvendio__Campaign_Item__c/CreateOptimization/ -H 'Authorization: Bearer <SESSION_ID>' -H "Content-Type: application/json" -H 'X-PrettyPrint:1' -d @requestBody.txt --request PATCH

1.8.4.2.
requestBody.txt

{
  "campaignItems":[
    {
      "ADvendio__Media_Campaign__c":"a1E2K00000KEBpOUAX",
      "ADvendio__Ad_Price__c":"a0HA000000Sn0X6MAJ",
      "ADvendio__Quantity__c":1000,
      "ADvendio__Sales_Price__c": 30,
      "ADvendio__from_Date__c":"2020-07-30 00:00:00",
      "ADvendio__until_Date__c":"2020-07-30 00:00:00",
      "ADvendio__SelectedContent__r":{
        "records":[
          {
            "ADvendio__Content__c":"a0eA000000GcZkIIAV"
          },{
            "ADvendio__Content__c":"a0e2K000007NukcQAC"
          }
        ]
      }
    }
  ]
}

1.8.4.3.
Response

[
  {
    "attributes":{
      "type":"ADvendio__OptimizingVersion__c","url":"/services/data/v49.0/sobjects/ADvendio__OptimizingVersion__c/a1I2K00000FwP7fUAF"
    },
    "Name":"2_30.07.2020",
    "ADvendio__MediaCampaign__c":"a1E2K00000KEBpOUAX",
    "CurrencyIsoCode":"EUR",
    "ADvendio__OptimizingChanges__r":{
      "totalSize":88,
      "done":true,
      "records":[
        {
          "attributes":{
            "type":"ADvendio__OptimizingChange__c",            
          },
          "ADvendio__CampaignItem__c":"a0Y2K00000Fe82gUAB",            
         "ADvendio__FieldName__c":"name",            
          "ADvendio__OptimizedValue__c":"Test Name",            
          "ADvendio__NewCiIdentifier__c":"a0YXX00XX0000012MA",            
         "CurrencyIsoCode":"EUR"
        },{            
          "attributes":{
            "type":"ADvendio__OptimizingChange__c",            
            "url":"/services/data/v49.0/sobjects/ADvendio__OptimizingChange__c/a1H2K00000iD0qNUAS"
          },
          "ADvendio__CampaignItem__c":"a0Y2K00000Fe82gUAB",            
          "ADvendio__FieldName__c":"advendio__ad_price__c",            
          "ADvendio__OptimizedValue__c":"a0HA000000Sn0X6MAJ",            
          "ADvendio__NewCiIdentifier__c":"a0YXX00XX0000012MA",            
          "CurrencyIsoCode":"EUR"
        },{            
          "attributes":{
            "type":"ADvendio__OptimizingChange__c",            
            "url":"/services/data/v49.0/sobjects/ADvendio__OptimizingChange__c/a1H2K00000iD0qpUAC"
          },
          "ADvendio__CampaignItem__c":"a0Y2K00000Fe82gUAB",            
          "ADvendio__FieldName__c":"advendio__quantity__c",            
          "ADvendio__OptimizedValue__c":"1000.00",            
          "ADvendio__NewCiIdentifier__c":"a0YXX00XX0000012MA",            
          "CurrencyIsoCode":"EUR"
        },{            
          "attributes":{
            "type":"ADvendio__OptimizingChange__c",            
            "url":"/services/data/v49.0/sobjects/ADvendio__OptimizingChange__c/a1H2K00000iD0r1UAC"
          },
          "ADvendio__CampaignItem__c":"a0Y2K00000Fe82gUAB",            
          "ADvendio__FieldName__c":"advendio__from_date__c",            
          "ADvendio__OptimizedValue__c":"2020-07-30 00:00:00",            
          "ADvendio__NewCiIdentifier__c":"a0YXX00XX0000012MA",            
          "CurrencyIsoCode":"EUR"
        },{            
          "attributes":{
            "type":"ADvendio__OptimizingChange__c",            
            "url":"/services/data/v49.0/sobjects/ADvendio__OptimizingChange__c/a1H2K00000iD0r2UAC"
          },
          "ADvendio__CampaignItem__c":"a0Y2K00000Fe82gUAB",            
          "ADvendio__FieldName__c":"advendio__until_date__c",            
          "ADvendio__OptimizedValue__c":"2020-07-30 00:00:00",            
          "ADvendio__NewCiIdentifier__c":"a0YXX00XX0000012MA",            
          "CurrencyIsoCode":"EUR"
        },{
          "attributes":{
            "type":"ADvendio__OptimizingChange__c",
            "url":"/services/data/v49.0/sobjects/ADvendio__OptimizingChange__c/a1H2K00000iD0yYUAS"
          },
          "ADvendio__CampaignItem__c":"a0Y2K00000Fe82gUAB",
          "ADvendio__FieldName__c":"advendio__selectedcontent__r",
          "ADvendio__OptimizedValue__c":"a0eA000000GcZkIIAV,a0e2K000007NukcQAC",
          "CurrencyIsoCode":"EUR"
        }
      ]
    }
  }
]

1.9. Usage in Apex

List<ADvendio__Campaign_Item__c> cis = ...
ADvendio__OptimizingVersion__c optimizingVersion = ADvendio.OptimizerService.createOptimization(cis);
optimizingVersion.ADvendio__Source__c = 'reactive'; // set OptimizerVersion fields as you need them
insert optimizingVersion;

List<ADvendio__OptimizingChange__c> changes = new List<ADvendio__OptimizingChange__c>();
for (ADvendio__OptimizingChange__c change : optimizingVersion.ADvendio__OptimizingChanges__r) {
  change.ADvendio__OptimizingVersion__c = optimizingVersion.Id;
  changes.add(change);
}
insert changes;