Discussions
Eloqua 478/479 Sneak Peek: Lead Scoring is Coming to the Bulk API

With the Oracle Eloqua 478/479 release, lead scoring models and fields are coming to the Bulk API. I am going to walk through an end to end scenario with examples, but before I do that here are some of the highlights:
- Lead scoring models and their corresponding lead scoring fields will be discoverable via the Bulk API
- Lead scoring fields will be available to be used in Bulk API contact export definitions
- There could only be one lead scoring model used per contact export definition
- Each lead scoring model has three lead scoring fields available:
- Rating
- Profile Score
- Engagement Score
- Lead scoring fields can be used in contact export filter statements
With the key takeaways highlighted, let's now take a look at this new functionality in action. I'm going to walk through finding a lead scoring model, using those lead scoring fields in a contact export definition, and completing the scenario by retrieving some contacts. Along the way we'll also use a lead scoring field in a filter statement and, as a bonus, I'll be highlighting an additional improvement in regards to contact exports. Total FOMO should now be in place!
Let's start by retrieving two lead scoring models:
Request
GET /API/Bulk/2.0/contacts/scoring/models?limit=2
Response
200 OK { "items": [ { "name": "Test 1", "status": "Draft", "id": 1, "fields": [ { "name": "Rating", "statement": "{{Contact.LeadScore.Model[1].Rating}}", "dataType": "string" }, { "name": "ProfileScore", "statement": "{{Contact.LeadScore.Model[1].ProfileScore}}", "dataType": "number" }, { "name": "EngagementScore", "statement": "{{Contact.LeadScore.Model[1].EngagementScore}}", "dataType": "number" } ], "uri": "/contacts/scoring/models/1", "createdBy": "Lou.Patrick", "updatedBy": "Lou.Patrick", "createdAt": "2015-01-15T18:44:58.9930000Z", "updatedAt": "2015-07-02T18:03:19.1930000Z" }, { "name": "Test 2", "status": "Draft", "id": 2, "fields": [ { "name": "Rating", "statement": "{{Contact.LeadScore.Model[2].Rating}}", "dataType": "string" }, { "name": "ProfileScore", "statement": "{{Contact.LeadScore.Model[2].ProfileScore}}", "dataType": "number" }, { "name": "EngagementScore", "statement": "{{Contact.LeadScore.Model[2].EngagementScore}}", "dataType": "number" } ], "uri": "/contacts/scoring/models/2", "createdBy": "Lou.Patrick", "updatedBy": "Lou.Patrick", "createdAt": "2015-01-15T18:45:09.9930000Z", "updatedAt": "2015-07-02T18:18:01.6570000Z" } ], "totalResults": 6, "limit": 2, "offset": 0, "count": 2, "hasMore": true }
I do not see the lead scoring model I'm looking for; however, I see there are four more lead scoring models. I could remove the limit and return all lead scoring models but I know the name of the lead scoring model I want so let's use a query parameter to retrieve a lead scoring model by name and, because I'm not sure on the exact name, we'll use some wildcards:
Request
GET /API/Bulk/2.0/contacts/scoring/models?q="name=*Oscar*"
Response
200 OK { "items": [ { "name": "Oscar Cleaning", "status": "Active", "id": 6, "fields": [ { "name": "Rating", "statement": "{{Contact.LeadScore.Model[6].Rating}}", "dataType": "string" }, { "name": "ProfileScore", "statement": "{{Contact.LeadScore.Model[6].ProfileScore}}", "dataType": "number" }, { "name": "EngagementScore", "statement": "{{Contact.LeadScore.Model[6].EngagementScore}}", "dataType": "number" } ], "uri": "/contacts/scoring/models/6", "createdBy": "Lou.Patrick", "updatedBy": "Lou.Patrick", "createdAt": "2016-03-22T17:20:54.6100000Z", "updatedAt": "2016-03-22T18:20:39.3000000Z" } ], "totalResults": 1, "limit": 1000, "offset": 0, "count": 1, "hasMore": false }
There's the one I'm looking for. Now let's create a contact export definition using the lead scoring fields for the Oscar Cleaning lead scoring model:
Request
POST /API/Bulk/2.0/contacts/exports
Request - Body
{ "name": "Contact Lead Score Export - Oscar Cleaning", "fields": { "EmailAddress": "{{Contact.Field(C_EmailAddress)}}", "FirstName": "{{Contact.Field(C_FirstName)}}", "LastName": "{{Contact.Field(C_LastName)}}", "Rating": "{{Contact.LeadScore.Model[6].Rating}}", "Profile": "{{Contact.LeadScore.Model[6].ProfileScore}}", "Engagement": "{{Contact.LeadScore.Model[6].EngagementScore}}", "AcademyAwards": "{{Contact.Field(C_Academy_Awards1)}}" } }
Response
201 Created { "name": "Contact Lead Score Export - Oscar Cleaning", "fields": { "EmailAddress": "{{Contact.Field(C_EmailAddress)}}", "FirstName": "{{Contact.Field(C_FirstName)}}", "LastName": "{{Contact.Field(C_LastName)}}", "Rating": "{{Contact.LeadScore.Model[6].Rating}}", "Profile": "{{Contact.LeadScore.Model[6].ProfileScore}}", "Engagement": "{{Contact.LeadScore.Model[6].EngagementScore}}", "AcademyAwards": "{{Contact.Field(C_Academy_Awards1)}}" }, "dataRetentionDuration": "PT12H", "uri": "/contacts/exports/5", "createdBy": "Lou.Patrick", "createdAt": "2016-03-22T19:22:05.2099774Z", "updatedBy": "Lou.Patrick", "updatedAt": "2016-03-22T19:22:05.2099774Z" }
With our uri in hand, we are now ready to create the sync:
Request
POST /API/Bulk/2.0/syncs
Request - Body
{ "syncedInstanceUri": "/contacts/exports/5" }
Response
201 Created { "syncedInstanceUri": "/contacts/exports/5", "status": "pending", "createdAt": "2016-03-22T19:34:44.7980550Z", "createdBy": "Lou.Patrick", "uri": "/syncs/2" }
Ideally we'd be using the callbackUrl parameter to allow Eloqua to alert us when the sync is complete. For simplicity of demonstration, I'll GET the sync details to confirm it was successful:
Request
GET /API/Bulk/2.0/syncs/2
Response
200 OK { "syncedInstanceUri": "/contacts/exports/5", "syncStartedAt": "2016-03-22T19:34:47.2570000Z", "syncEndedAt": "2016-03-22T19:34:48.5000000Z", "status": "success", "createdAt": "2016-03-22T19:34:45.0030000Z", "createdBy": "Lou.Patrick", "uri": "/syncs/2" }
Success! Now it's time to retrieve the data:
Request
GET /API/Bulk/2.0/syncs/2/data
Response
200 OK { "totalResults": 13, "limit": 1000, "offset": 0, "count": 13, "hasMore": false, "items": [ { "EmailAddress": "[email protected]", "FirstName": "", "LastName": "", "Rating": "D4", "Profile": "0", "Engagement": "0", "AcademyAwards": "" }, { "EmailAddress": "[email protected]", "FirstName": "Lou", "LastName": "Patrick", "Rating": "D4", "Profile": "0", "Engagement": "0", "AcademyAwards": "" }, { "EmailAddress": "[email protected]", "FirstName": "Test12", "LastName": "", "Rating": "D4", "Profile": "0", "Engagement": "0", "AcademyAwards": "" }, { "EmailAddress": "[email protected]", "FirstName": "", "LastName": "", "Rating": "D4", "Profile": "0", "Engagement": "0", "AcademyAwards": "" }, { "EmailAddress": "[email protected]", "FirstName": "", "LastName": "", "Rating": "D4", "Profile": "0", "Engagement": "0", "AcademyAwards": "" }, { "EmailAddress": "[email protected]", "FirstName": "", "LastName": "", "Rating": "D4", "Profile": "0", "Engagement": "0", "AcademyAwards": "" }, { "EmailAddress": "[email protected]", "FirstName": "Whoopi", "LastName": "Goldberg", "Rating": "B1", "Profile": "70", "Engagement": "100", "AcademyAwards": "1.0000" }, { "EmailAddress": "[email protected]", "FirstName": "Meryl", "LastName": "Streep", "Rating": "A3", "Profile": "100", "Engagement": "30", "AcademyAwards": "3.0000" }, { "EmailAddress": "[email protected]", "FirstName": "Tom", "LastName": "Hanks", "Rating": "A4", "Profile": "80", "Engagement": "0", "AcademyAwards": "2.0000" }, { "EmailAddress": "[email protected]", "FirstName": "Tom", "LastName": "Cruise", "Rating": "D1", "Profile": "0", "Engagement": "100", "AcademyAwards": "" }, { "EmailAddress": "[email protected]", "FirstName": "Arnold", "LastName": "Schwarzenegger", "Rating": "D2", "Profile": "0", "Engagement": "70", "AcademyAwards": "" }, { "EmailAddress": "[email protected]", "FirstName": "Jack", "LastName": "Nicholson", "Rating": "A1", "Profile": "100", "Engagement": "100", "AcademyAwards": "3.0000" }, { "EmailAddress": "[email protected]", "FirstName": "Natalie", "LastName": "Portman", "Rating": "B4", "Profile": "70", "Engagement": "0", "AcademyAwards": "1.0000" } ] }
There are not many contacts in this test instance but there are some clear test contacts and also some contacts we'd want to remove as they do not have any Academy Awards. Next, we'll create a new contact export definition and filter on the Profile lead scoring field, removing all contacts from our export with a Profile value of "0":
Request
POST /API/Bulk/2.0/contacts/exports
Request - Body
{ "name": "Contact Lead Score Export - Oscar Cleaning - Filtered", "fields": { "EmailAddress": "{{Contact.Field(C_EmailAddress)}}", "FirstName": "{{Contact.Field(C_FirstName)}}", "LastName": "{{Contact.Field(C_LastName)}}", "Rating": "{{Contact.LeadScore.Model[6].Rating}}", "Profile": "{{Contact.LeadScore.Model[6].ProfileScore}}", "Engagement": "{{Contact.LeadScore.Model[6].EngagementScore}}", "AcademyAwards": "{{Contact.Field(C_Academy_Awards1)}}" }, "filter": "'{{Contact.LeadScore.Model[6].ProfileScore}}' > '0'" }
Response
201 Created { "name": "Contact Lead Score Export - Oscar Cleaning - Filtered", "fields": { "EmailAddress": "{{Contact.Field(C_EmailAddress)}}", "FirstName": "{{Contact.Field(C_FirstName)}}", "LastName": "{{Contact.Field(C_LastName)}}", "Rating": "{{Contact.LeadScore.Model[6].Rating}}", "Profile": "{{Contact.LeadScore.Model[6].ProfileScore}}", "Engagement": "{{Contact.LeadScore.Model[6].EngagementScore}}", "AcademyAwards": "{{Contact.Field(C_Academy_Awards1)}}" }, "filter": "'{{Contact.LeadScore.Model[6].ProfileScore}}' > '0'", "dataRetentionDuration": "PT12H", "uri": "/contacts/exports/6", "createdBy": "Lou.Patrick", "createdAt": "2016-03-22T20:16:32.6099108Z", "updatedBy": "Lou.Patrick", "updatedAt": "2016-03-22T20:16:32.6099108Z" }
We'll skip over showing examples for creating the sync and confirming it was successful, as it's identical to the examples above. From creating the sync the resulting uri is "/syncs/3". Let's jump to retrieving data from our filtered contact export definition sync:
Request
GET /API/Bulk/2.0/syncs/3/data
Response
200 OK { "totalResults": 5, "limit": 1000, "offset": 0, "count": 5, "hasMore": false, "items": [ { "EmailAddress": "[email protected]", "FirstName": "Whoopi", "LastName": "Goldberg", "Rating": "B1", "Profile": "70", "Engagement": "100", "AcademyAwards": "1.0000" }, { "EmailAddress": "[email protected]", "FirstName": "Meryl", "LastName": "Streep", "Rating": "A3", "Profile": "100", "Engagement": "30", "AcademyAwards": "3.0000" }, { "EmailAddress": "[email protected]", "FirstName": "Tom", "LastName": "Hanks", "Rating": "A4", "Profile": "80", "Engagement": "0", "AcademyAwards": "2.0000" }, { "EmailAddress": "[email protected]", "FirstName": "Jack", "LastName": "Nicholson", "Rating": "A1", "Profile": "100", "Engagement": "100", "AcademyAwards": "3.0000" }, { "EmailAddress": "[email protected]", "FirstName": "Natalie", "LastName": "Portman", "Rating": "B4", "Profile": "70", "Engagement": "0", "AcademyAwards": "1.0000" } ] }
Now we have filtered results including only contacts that have at least one Academy Award. That completes the walk through of the lead scoring capabilities coming to the Bulk API. So now I bet everyone wants to mark their calendars with the date 478/479 will arrive for them!
When will I receive the 478/479 release? Visit the to view roll out dates.
How about documentation? When version 478/479 is rolled out to POD2, the Oracle Eloqua Developer Help Center will be updated with the new endpoints and examples. (Documentation now updated: Lead scoring models)
Interested in more related to Eloqua APIs and the 478/479 release? Take a look at the Developer Release Notes - 478/479.
Happy coding with the Eloqua APIs and see you around Code It!
Comments
-
@Lou Patrick Is it possible that this release has stopped notification URLs from working within AppService Content Services?
I have a Content Service app deployed on POD2. Since Tuesday I am receiving no hits to the notification url. I am looking directly at the traffic (proxy logs capture everything) to confirm there is no request whatsoever.
The configure/delete URLs all work fine. Configuration is being acknowledged as success, etc.
The exact same app deployed on POD3 receives the notification URL successfully.
This suggests to me that either a) there is a transient failure, b) this release accidentally broke Content Service notification URLs, or c) the service responsible is down for POD2 (possibly never re-enabled after maintenance).
I'd appreciate your thoughts on this asap!
-
Lou Patrick Principal Product Manager, Eloqua APIs & App Developer Framework Portland, ORPosts: 174 Bronze Trophy
@Lou Patrick Is it possible that this release has stopped notification URLs from working within AppService Content Services?
I have a Content Service app deployed on POD2. Since Tuesday I am receiving no hits to the notification url. I am looking directly at the traffic (proxy logs capture everything) to confirm there is no request whatsoever.
The configure/delete URLs all work fine. Configuration is being acknowledged as success, etc.
The exact same app deployed on POD3 receives the notification URL successfully.
This suggests to me that either a) there is a transient failure, b) this release accidentally broke Content Service notification URLs, or c) the service responsible is down for POD2 (possibly never re-enabled after maintenance).
I'd appreciate your thoughts on this asap!
@sam.smith Thanks for surfacing this and providing the detail. Also, thanks for posting this directly in Code It, as questions will always get more exposure if you create a new post/question in the forum.
We are looking into this.
-
Do you if Eloqua is saving a history of the lead score and if it´s possible to grap the information with Bulk API?
Looking forward to your feedback. :-)
-
Lou Patrick Principal Product Manager, Eloqua APIs & App Developer Framework Portland, ORPosts: 174 Bronze Trophy
Do you if Eloqua is saving a history of the lead score and if it´s possible to grap the information with Bulk API?
Looking forward to your feedback. :-)
Eloqua does not save the history for a lead score.
-
Adrian Chang-Oracle Director, Customer Programs at Oracle Marketing Cloud San Francisco, CAPosts: 38 Employee
Eloqua does not save the history for a lead score.
@zweiler If you had a contact field for the historical lead score, you could have business logic that tracks the historical score and pass that to CRM and pick a frequency for managing the changes (monthly, quarterly, etc). Scoring shows how the buyer would respond to a conversation from sales at a particular point in time so you would have to determine what would work for you based on your process.
-
Eloqua does not save the history for a lead score.
@Lou Patrick, @Adrian Chang-Oracle,
Eloqua does indeed store a lead score history. It's just not exposed in the API, is it?
-
Lou Patrick Principal Product Manager, Eloqua APIs & App Developer Framework Portland, ORPosts: 174 Bronze Trophy
@Lou Patrick, @Adrian Chang-Oracle,
Eloqua does indeed store a lead score history. It's just not exposed in the API, is it?
Yes, you can view the lead score history in the UI, so it is being stored, but only the current lead score is available via the API.
-
Adrian Chang-Oracle Director, Customer Programs at Oracle Marketing Cloud San Francisco, CAPosts: 38 Employee
Yes, you can view the lead score history in the UI, so it is being stored, but only the current lead score is available via the API.
Thanks @Lou Patrick! Customers should be thinking through some scenarios for how they can leverage the API to deliver this data for the following reasons:
- partner for predictive scoring
- Audit your existing lead scoring program
- Send lead scores for Business Unit A into CRM for Business Unit B
Am I on the right track? How do our fellow Topliners envision using this information.
-
Is it possible to perform an extract of lead scores directly within the GUI rather than use the API?