Skip navigation
1 2 3 4 Previous Next

Code It

57 Posts authored by: TJ Fields-Oracle

With Eloqua's Summer release, a new RESTful endpoint was developed for retrieving a visitor profile.

 

Here is an example of its usage:

 

Request

GET /API/REST/2.0/data/visitors?count={count}&page={page}&search={search}&orderBy={orderBy}&lastUpdatedAt={lastUpdatedAt}

 

Response

{

    "elements": [

        {

            "type": "VisitorViewData",

            "visitorId": "88888",

            "createdAt": "1395423247",

            "V_IPAddress": "127.0.0.1",

            "V_LastVisitDateAndTime": "1395426873",

            "externalId": "a10746a6-2480-425b-9db7-f20f4ac1c37e",

            "contactId": "8"

        }

    ],

    "page": 1,

    "pageSize": 5,

    "total": 1

}

   

 

The response contains information from the Visitor profile in Eloqua.  The information you can currently retrieve is:

 

FieldDescrption
visitorIdThe ID of the Visitor profile
createdAtDate the Visitor profile was created
V_IPAddressIP address of the Visitor
V_LastVisitDateAndTimeDate of last visit to an Eloqua asset for this profile
externalIdCustomer GUID for this Visitor profile
contactidThe Contact record ID associated to this profile, if any

 

One common usage scenario for this endpoint is retrieving Eloqua Contact information when all you have is a GUID from the Eloqua cookie.  For example:

 

  • Search for a Visitor profile by the externalId using the GUID, a10746a6-2480-425b-9db7-f20f4ac1c37e.

GET /API/REST/2.0/data/visitors?search=externalId=a10746a6-2480-425b-9db7-f20f4ac1c37e&page=1&count=5

  

 

  • From the response, grab the contactId (if there is one)
  • Use the Eloqua API to look up the Contact record by ID

 

For more information on:

ATTENTION: We recently announced that support for the SOAP API would end in October 2015.  For details, please see Support for SOAP is Ending

 

The Eloqua SOAP API documentation can now be found in the attached PDF.

 

NOTE: This is the documentation that was previously hosted on www.eloquatrainingcenter.com, which has now been shut down.

Looking for a high-level overview of the available Eloqua APIs?

 

Recently, there was a great post done that explains the different APIs along with brief description of each.

 

Check it out here A Beginner’s Guide to the Eloqua API

TJ Fields-Oracle

New Code It Badges

Posted by TJ Fields-Oracle Sep 5, 2013

Attention developers...

 

We now have our own Topliners badges!!!!

 

As we all know, the only way to make a development community work is to have members share their insight, and assist fellow developers by participating in discussions.  As a way of recognizing those who regularly contribute, we've come up with two badges specific to Code It.

 

Here are the details:

 

By answering 5 questions, you can earn 75 points and become a Code It Professor.

 

To become a Code It Guru, you will need to answer 20 questions, but you will get 200 points.

 

"Answering" a question means having them marked either Correct or Helpful by the community.

 

You will see the Missions, as well as your own progress for each, displayed on the right hand side of the main Code it page for easy tracking!

 

Let the gaming begin :-)

In the post Building Cloud Components: Testing we introduced you to the Cloud Component Test Utility.

 

Since there is currently no way to test your component within Eloqua, the purpose of the test utility is to ensure that all of your endpoints are working correctly.  This post will walk you through this process step-by-step.

 

Let's get started...

 

When you first navigate to the tool in your browser, you'll see the following:

Main.png

 

Enter the URL to your provider's service definition in the box at the top, then click Test.

Test.png

To tool will then attempt to parse your JSON.  If your provider is successfully parsed, you'll see your JSON and a list of components in the corresponding sections.

Test_Result.png

 

From the Components list, select the component you wish to test, and click the + (plus) sign.  This will call your createInstance endpoint, therefore creating an instance of your component.

 

If your component instance was successfully created, it will be displayed in the Instances section.

AddNew.png

Next, let's test out the Configure endpoint.  Highlight the newly created component and click the wrench icon.  Your configuration page should open in a pop-up.

Config.png

Configure your component and then close the window.

 

Now it's time to test the Render endpoint.  Click the eye icon at the bottom of the page.

Rendered_Content.png

If all worked correctly, your Snapshot and Rendered Content areas should be populated.

 

The last check is the Remove endpoint.  To test this, click the - (minus) sign.

Delete_or_Submit.png

 

Your component instance should be removed from the window, as well as from your system.

 

Once all of your endpoints have been tested successfully, it's time to Submit your app for approval.  Click the Submit button, and the following form will appear.

 

Submit.png

 

Fill in the information and click Submit.  This will kick off the approval process, and you'll be one step closer to having your component in Eloqua and onto the AppCloud!

 

Some things to keep in mind:

 

  • The test utility does not provide much in the way of error messages, so if you're experiencing issues, I recommend using a utility such as Fiddler to see what is going wrong.
  • If your JSON will not correctly parse, make sure that your content-type is correct (text/json or application/json), and that you are bringing back valid JSON.  Use a tool such as JSONLint to check this.

Now that you've built your Cloud Connector, it's time to get your service "installed" in Eloqua, so that it can be chosen in the cloud connector step on the Canvas or in Program Builder.

 

Let's take a look at how an Eloqua Customer Administrator manages cloud connectors in the application.

 

Under Setup...Database, there is an icon titled Cloud Connector.

CloudConnectorSetup.PNG

Clicking on this icon will take you to the Cloud Connector Management area.

CloudConnectorManagement.png

 

On this screen, you will see the Current Registered Services table.  This is where you want your new connector to appear, as it is these connectors that appear in the select list on the program step.


In order to register a new cloud connector service, the Customer Administrator will need the following three (3) pieces of information:

 

    • Service Name - a name for the connector (this is the friendly name that will show in the drop-down when setting up the step)
    • Service URL: the URL to your configuration page.  This URL must ask for STEP_ID and COMPANY.  When the user clicks the configuration button from the step, Eloqua will call your URL and pass the Step ID and Eloqua Company to you as parameters.

               For Example: https://myconnectorservice.com/config.aspx?StepID={STEP_ID}&Company={COMPANY}

    • Unique Id:  a unique name for your connector (this must be unique in the Current Registered Services table/list.

 

Once your service (connector) is "installed", when the user creates a Cloud Connector step, they will see your connector in the list, and be able to select it, then click the configuration button to set it up.

Canvas2.png

You can then take the STEP_ID and COMPANY parameters that were sent, and use those to aid in the configuration.  This eliminates the need for the user to provide your app with the Company and Step, which would be needed if they were using the Manual setup (by clicking the check-box instead of selecting from the list).

 

Things to keep in mind:

 

  • Only an Eloqua Customer Administrator can see and access the Cloud Connector Management area in an Eloqua install.
  • Your URL *MUST* request the STEP_ID and COMPANY, but you can choose whether or not to use it.
  • You do not need to install your connector in Eloqua, this is optional.  The user can check the Manual box, and then go to your setup page on their own and enter the Step ID and other required information.

In previous posts, we looked at Eloqua API How To: Create and Retrieve a Data Card and Eloqua API How To: Mapping a Data Card to a Contact.  This time we will look at how to Update an existing Custom Data Object (or Data Card).

 

The code below will show you how to first retrieve the Data Card we want to update, modify a field value, then write that back to Eloqua.  Finally, we will pull back the DataCard and check the new value to confirm it was updated successfully.

 

Once again, I will be assuming that the code found Connecting to the Eloqua API - Generic Setup is being used to establish a connection to the Eloqua API.  It is also assumed that you know the ID of both the Data Card Set and Data Card that you wish to update, as well as the internal name of any field(s) to be updated.

 

As before, we will be using the EloquaService API. For more information on which API to use for specific functions, see Eloqua SOAP API - Which one do I use?.

 

Now, the code...

 

   class UpdateDataCard
    {
        static void Main()
        {
               var dataCardIDs = new int[1];
               string oldVal = "";
            
               try
               {
                    var service = new EloquaInstance("instance", "userid", "password");

                    // Build a DataCardSet Entity Type object - (the ID is the ID of an existing DataCardSet in Eloqua)
                    EntityType entityType = new EntityType { ID = 55, Name = "DataCardSet", Type = "DataCardSet" };

                    // Set the ID of the DataCard Entity
                    dataCardIDs[0] = 301677;

                    // Create a new list containing the fields you want populated
                   List<string> fieldList = new List<string>();

                    // Add the DataCard’s Title to the field list (this is the field we will update)
                   fieldList.Add("Title1");

                    // Build a Dynamic Entity array to store the results
                    DynamicEntity[] retrievedEntities;

                    // If the field list is empty - the request will return all Entity Fields
                   // Otherwise, only fields defined in the field list are returned
                   retrievedEntities = service.ServiceProxy.Retrieve(entityType, dataCardIDs, fieldList.Count == 0 ? null : fieldList.ToArray());

                    // Make sure a result was found
                    if (retrievedEntities.Length > 0)
                    {
                         foreach (DynamicEntity dynamicEntity in retrievedEntities)
                         {
                             //Save the old value so that we can confirm the change
                             oldVal = dynamicEntity.FieldValueCollection["Title1"];
                             //Update the value
                             dynamicEntity.FieldValueCollection["Title1"] = "A new value!";
                         }

                         //Perform the Update
                    service.ServiceProxy.Update(retrievedEntities);

                       Console.WriteLine("DataCard Updated Successfully!");
                    }

               //Now, pull the card again to make sure it updated
                retrievedEntities = service.ServiceProxy.Retrieve(entityType, dataCardIDs, fieldList.Count == 0 ? null : fieldList.ToArray());

               // Make sure a result was found
                if (retrievedEntities.Length > 0)
                {
                    foreach (DynamicEntity dynamicEntity in retrievedEntities)
                    {
                        Console.WriteLine(String.Format("Title was changed from \"{0}\" to \"{1}\"", oldVal, dynamicEntity.FieldValueCollection["Title1"]));
                    }
                         // Customize your own error handling
                  }
            catch (System.ServiceModel.FaultException ex)
            {
                // Catch Service Model Fault Exceptions
                Console.WriteLine(String.Format("Reson: {0}", ex.Reason.ToString()));
                Console.WriteLine(String.Format("Fault Type: {0}", ex.GetType().ToString()));
                Console.WriteLine(String.Format("Fault Code: {0}", ex.Code.Name.ToString()));
            }
          catch (Exception ex)
            {
                // Catch System Exceptions
                Console.WriteLine(String.Format("Exception Message: {0}", ex.Message.ToString()));
            }

            // Wait for user input before stepping out.
            Console.WriteLine("Press any key to continue.");
            Console.ReadKey();

        }
    }


When the program is run, a console window will pop up showing the results as seen below.


fileCUserstfields.png

Recently, one of our partners developed a Ruby client for the Eloqua API.

 

If you are using Ruby to build on the Eloqua platform, you will definitely want to check it out.

 

Code is available here kapost/eloqua_api · GitHub

 

Gem is publicly available here eloqua_api | RubyGems.org | your community gem host

 

Happy coding!

 

Please note, this code is not supported by Eloqua, as it was developed by a third party.

Important:  Documentation for this topic is available in our new Oracle Eloqua Developer Help Center.


Eloqua recently made some infrastructure changes in support of additional data centers.  To support these additional data centers, a new API endpoint was created to allow you to interface with Eloqua regardless of where the Eloqua install is located.  In this post we share details of this new endpoint.

 

Until now, almost all customers resided in the same production environment.  The API could therefore be accessed using the base URL of https://secure.eloqua.com.  In the coming months, new customers will be deployed in the new data centers, and some customers may move between data centers, and will therefore have a different URL than what you have seen in the past.

 

What does this mean to you as a developer?

 

Depending on the Eloqua customer that is trying to use your app, your API calls may no longer work!

 

Here's the good news...

 

There is now an endpoint that allows you to determine the URL for your API calls.  This endpoint is https://login.eloqua.com/id.

 

The endpoint, when called with basic authentication or OAuth authentication, will return details about the URLs for the various APIs.

 

Here's how to use it:

 

Request (basic authentication):

GET https://login.eloqua.com/id HTTP/1.1
Authorization: Basic XXXXX

 

Response (success):

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 824

 

{
    "site": {
        "id": 42,
        "name": "MyTestInstall"
    },
    "user": {
        "id": 314,
        "username": "TJ.Fields",
        "displayName": "TJ Fields",
        "firstName": "TJ",
        "lastName": "Fields",
        "emailAddress": "tj.fields@eloqua.com"
    },
    "urls": {
        "base": "https://www05.secure.eloqua.com",
        "apis": {
            "soap": {
                "standard": "https://www05.secure.eloqua.com/API/{version}/Service.svc",
                "dataTransfer": "https://www05.secure.eloqua.com/API/{version}/DataTransferService.svc",
                "email": "https://www05.secure.eloqua.com/API/{version}/EmailService.svc",
                "externalAction": "https://www05.secure.eloqua.com/API/{version}/ExternalActionService.svc"
            },
            "rest": {
                "standard": "https://www05.secure.eloqua.com/API/REST/{version}/",
                "bulk": "https://www05.secure.eloqua.com/API/Bulk/{version}/"
            }
        }
    }
}

Now that you have the URLs for the API(s), you can use them in your code.


Response (failure):

HTTP/1.1 200 OK

Content-Type: application/json; charset=utf-8

Content-Length: 20

 

"Not authenticated."


Your applications must cache the data they need from the /id endpoint for the duration of the user's session or for a reasonable period of time:

 

They must not call the /id endpoint once per API call, as there will be throttling or rate-limiting imposed on the /id endpoint to prevent this behavior:

 

Tip: When calling this endpoint from a  Cloud Connector or Cloud Component app,  if an API call fails with a 401, your application should call the /id endpoint again to determine whether the 401 was the result of the user's credentials/token being invalidated, or the result of the site being moved to a different data center.  If the /id endpoint returns a failure, your application should stop making API calls.  If the /id endpoint returns a success, your application should retry the API call at the new address in the response.

 

Here's a quick flowchart showing the fallback process:

image.png

 

 

Interactive applications can respond to 401s using this process, or by simply logging the user out.

 

Frequently Asked Questions

 

  • Q: What URL should I use?
    • A: Use login.eloqua.com/id to determine your base URL, and use the base with your existing calls.
  • Q: What permissions do I need to call login.eloqua.com/id?
    • A: The user calling login.eloqua.com/id needs, at a minimum, the API Users and Advanced Users - Marketing permissions.

 

 

If you have any questions, post a Discussion to Code It!

In previous posts about building cloud components, specifically in reference to the renderInstance endpoint, we touched on the ability to receive additional parameters from the Cloud Components framework.

 

By adding extra query string parameters to your endpoint address, an Asset ID, Contact ID, or Visitor ID can be passed by the Eloqua platform into your application.

 

As an example, let's look at the following endpoint address.

 

https://mycompany.com/ccpservice/components/render/{Id}&assetId={AssetId}&contactId={ContactId}&visitorId={VisitorId}

 

Notice that, in addition to the {Id} parameter, this service is requesting values be merged into {AssetId}, {ContactId}, and {VisitorId}.  When the Eloqua landing page is rendered, and this endpoint is called, the landing page ID (AssetId), Eloqua contact ID of the page visitor (ContactId), and Eloqua visitor ID (VisitorId) will be passed to your application.  (Note: The contact ID and visitor ID will only be populated if the page visitor is a known Eloqua contact or cookied visitor)

 

Once your application receives these values, you can use them to "personalize" your component.  For instance, using the contact ID or visitor ID and the Eloqua API, you could look-up other information on the page visitor and use that to display targeted content.  Or, if you are a video provider, you could use this information to track viewing data, and build a Feeder to pass the data back into Eloqua.

 

As you can see, there are many possibilities, and I think you'll agree that this is a pretty powerful capability.

 

Keep this in mind when you are building your component!


In case you missed the post, I thought this one was worth mentioning again.

 

There is now a great reference guide available that describes how to Import and Export data using Eloqua's Bulk API (an extremely powerful new RESTful API for performing bulk operations).

 

You can find the document here: Eloqua Bulk API 1.0: Importing and Exporting Data

 

Happy coding!!!

When it comes to building cloud connectors, one of the most frequently requested features is the ability to have Eloqua *push* notifications out to an app, instead of having to go through the process of polling for members.

 

Well, I am very happy to report that the Eloqua platform development team is currently working on a framework for doing exactly this.

 

There are still few details, and a release date is not yet available, but it should work something like this:

 

When setting up your cloud connector within Eloqua, you will have the ability to specify a "callback" URL.  When an Eloqua program runs, and a Cloud Connector step is encountered, it will call this URL and notify you that your step now has members ready for processing by your app.  You can then take this information and call into the step to retrieve the members and process them accordingly.  Instead of polling on a scheduled basis, your app can simply wait until it is called in order to act.

 

I will post further updates as I have them, but thought I'd share this bit of really good news!

Cloud Connectors

 

Cloud Connectors allow you to extend the functionality of Program Builder or the the Campaign Canvas.  Build an application that you host outside of Eloqua, and use the ExternalActionService (or Cloud Connector) API to poll a step in a campaign, retrieve its members, and perform an action on them.  Examples of these actions could be to pull in data to append to a contact record from external systems, or trigger a registration for an event by passing the contacts information to an event provider.

 

For more information, see the Cloud Connectors section in the resource guide HERE.

 

Cloud Components (Deprecated)

 

     We are no longer accepting submissions for Cloud Components.  Until further notice, existing components will continue to work as usual, but no changes can be made to the provider definition.

 

     A new framework is now available, that contains the next version of Cloud Components, called AppCloud Content.


     The documentation for this framework can be found here:

 

http://docs.oracle.com/cloud/latest/marketingcs_gs/OMCBA/index.html

 

 

Feeders

 

A Feeder is an application that "feeds" data into an Eloqua instance, usually creating new contacts as leads, or appending data to an existing contact.  These applications are configured by the user outside of Eloqua, and generally run on a scheduled basis.  Common settings required by a feeder include credentials, field mappings, and contact lists for results.  The Eloqua APIs are used to create or modify contacts, companies, and custom data objects.

 

For more information on Feeders, see Building Cloud Connectors: What is a Feeder?

Now that we've seen:

Authentication

HTTP Verbs

URL Parameters

 

It's time to look at HTTP Request Headers.  The table below outlines the request headers used by the API.

 

Content-Type

Specifies the media type that the client is sending to the server. Use application/json.  If no value is supplied, an error will occur.

 

For example:

PUT https://.../data/contact/123

Content-Type: application/json

<the existing contact>


Note: For PUT and POST verbs, use of the Content-Type header is mandatory.

Accept

Specifies the media types that the client is willing to accept from the server.  If no value is supplied, or if the supplied value doesn't contain "application/json" then the response will be returned in JSON.

 

GET https://.../data/contact/123 Accept: application/json

GET https://.../data/contact/123

GET https://.../data/contact/123 Accept: text/html

 

Note: use of the Accept header is optional.

X-HTTP-Method-Override

Allows HTTP clients, that don't support the PUT or DELETE verbs, to use GET or POST to update and delete entities. If a verb value is supplied in the header, that value will be used in place of the actual request verb.

In the example below, both requests are functionally identical:

DELETE https://.../data/contact/123

GET https://.../data/contact/123

X-HTTP-Method-Override: DELETE

 

Note: use of the X-HTTP-Method-Override header is optional.

X-HTTP-Status-Code-Override

Allows HTTP clients that don't support or expose HTTP status codes, other than HTTP 200 OK, to indicate that the server should always respond with a specific HTTP status code.  If a status code value is supplied in the header, that status code will be used in place of the actual request status code.

In the example below, the request will always return HTTP 200 OK, regardless of whether or not the actual status is OK:

 

 

    GET https://.../data/contact/123

    X-HTTP-Status-Code-Override: 200

 

 

If a value is supplied for the header, the actual status code will be returned in the X-HTTP-Original-Status-Code response header.

Note: use of theX-HTTP-Status-Code-Override header is optional.

Now that we've seen how to Authenticate, and looked at HTTP Verbs, let's move on to the URL parameters supported by the API endpoints.


Most Eloqua API endpoints accept one or more standard parameters, but not all endpoints support ALL of these parameters.

 

The available parameters are outlined in the table below.

 

 

Id

Identifier for the entity on which to perform the operation  This value is actually part of the base URL, and not a URL parameter. An example can been seen in the request below, which would return a representation of the contact entity with the identifier 123:

GET https://.../data/contact/123

Note: The format of entity identifiers may change over time, so developers should treat entity identifiers as opaque strings and not as numbers.
DepthDepth or level of detail returned. This can be "minimal", "partial", or "complete". An example can been seen in the request below, which would return the root form folder with a depth of "complete":
GET https://.../assets/form/folder/root?depth=complete
CountMaximum number of entities to return. The value can be any whole number between 1 and 1000. An example can been seen in the request below, which would return a maximum of 20 landing pages:
GET https://.../assets/landingPages?count=20

Note: If the count parameter is not supplied, 1000 will be used by default.
Page

Specifies which page of entities to return, and can be any positive whole number.  The Count parameter determines the size (number of results) per page.  An example can been seen in the request below, which return the first page of 20 landing pages (results 1...20):


GET https://.../assets/landingPages?count=20


To return the second page of 20 landing pages (results 21...40):

 

GET https://.../assets/landingPages?page=2&count=20

 

To return the third page of 20 landing pages (results 41...60):

 

GET https://.../assets/landingPages?page=3&count=20


Note: If the page parameter is not supplied, 1 will be used by default.

Search

Specifies the search criteria used to retrieve entities. This is in the form of:

[{term} {operator}] {value}

 

Where {term} is the name of a field to filter on, {operator} is the comparison operator, and {value} is the value to compare the field with.

 

The following request would return all landing pages whose name contains the word "Test":

GET https://.../assets/landingPages?search=Test

 

Note: If {term} and {operator} are not supplied, the name field is compared to the value using the equality operator.

SortSpecifies the name of the property used to sort the returned entities. The value depends on the type of entity being sorted, with each entity having its own list of sortable properties. An example can been seen in the request below, which returns a list of contacts sorted by first name (Note: firstName and lastName are only relevant to contacts):

 

GET https://.../data/contacts?sort=firstName

 

...or by last name


GET https://.../data/contacts?sort=lastName

 

 

 

 

Note: If  the Sort parameter is not supplied, the the results are returned with a default sort.

Dir

Specifies the direction in which to sort the returned entities. The value can be "asc" for ascending or "desc" for descending.  So, for the sorting example by first name above:

GET https://.../data/contacts?sort=firstName&dir=asc

Note: If the dir parameter is not supplied, the default value "asc" is used.

StatusCodeOverride

Allows HTTP clients that don't support or expose HTTP status codes, other than HTTP 200 OK, to indicate that the server should always respond with a specific HTTP status code. If a value is supplied for the parameter, that value will be used as the status code. An example can been seen in the request below, which will always return HTTP 200 OK, regardless of whether or not the actual status is OK:

 

GET https://.../data/contact/123?statusCodeOverride=200

JsonpCallback

Indicates that the response should be returned as JSONP (or JSON with Padding). The value is used as the name of the callback function in the returned JavaScript. The value of the Accept request header is ignored, and the content returned is always of type application/javascript.

An example can been seen in the request below, which does not include the jsonpCallback parameter, and so the response is plain JSON:

GET https://.../system/user/current?depth=complete  HTTP/1.1 200 OK Content-Type: application/json  {"type":"User","createdAt":"1237228178","depth":"complete", ...}
...and the same request made with the jsonpCallback parameter.  (returns application/javascript, and the original JSON is now wrapped in a call to the specified callback function):
GET https://.../system/user/current?depth=complete &jsonpCallback=loadCurrentUser  HTTP/1.1 200 OK Content-Type: application/javascript  loadCurrentUser({"type":"User","id":"9","createdAt":"1237228178","depth":"complete",...});

Filter Blog

By date: By tag: