Skip navigation
1 2 3 Previous Next

Do It

540 posts

We use a picklist for our country drop downs in forms where the value matches the country code in SFDC.  It's a ugly string of characters that gives you no clue what the country value is when you see a notification email.

I am personally not great with javascript, but I've managed to get the country display value added to a hidden field so it is sent in the notification email with lots of googling.  To save you from googling here is the javascript:


//set value of hidden field from drop down list display text
function ddlselect () {

//set d to the drop down list
 var d = document.getElementById("fe44703");

//grab the display text of the selected item
 var displaytext=d.options[d.selectedIndex].text;

//set the value of the hidden field

window.onload = function() {document.getElementById("fe44703").addEventListener("change", ddlselect);}


In your form HTML you will be able to find the id values for your drop down list and hidden field.  In this example my drop down list is fe44703 and my hidden field is fe44715.  (Note: getElementByName is deprecated in HTML5).

Teiu Codrin

Delete accounts in bulk

Posted by Teiu Codrin May 6, 2019



This post will cover a specific situation encountered when attempting to delete Eloqua accounts in bulk.


Default facts:

- If account linkage is set up, the unique identifier for accounts is the one set in the account linkage;

- if account linkage is NOT set up, the default identifier is CompanyName;


What scenario we will cover:

- Account linkage not set up (thus the default unique is Company Name), but our real unique and the one by which we want to delete is another account field, let's say a CompanyID.



- cannot delete based on a different identifier neither via the upload menu nor API, as the system takes CompanyName as default identifier.



1. Create an account group

Go to Audience/Tools/Account Groups and create new group to delete. In its top menu there is an Add Companies button. Select to add using Company Filter.


2. Create the filter

After going for the filter option at step 1 a window will pop up. Select Create New, name it, then add company fields(like CompanyID) by dragging them from one side to the other.

This is where you filter out and create your list of accounts to delete. Be very specific, the number will be confirmed at the bottom. The value for Total Number of Companies should reflect the number of accounts to be deleted.

Save and Close.

Make sure to select again the filter you just created and click continue.


3. Delete records

Review the list obtained. If it is ok then proceed to the top right menu of the account group and select Data Manipulation. Pick Delete Group Companies from Database.


I hope this helps,

A Long time ago, in an Eloqua Instance far, far away….


There were two fields: Lead source - Original and Lead Source - Most recent.

The battle for revenue attribution supremacy was fierce, but some people still asked “what was the deal?”, & “why do those fields even exist?”

Well, it is simple,... and if you so wish, I shall train you young Marketing ones, in 'the ways of the Source’.


The purpose of these fields is to give you some clear information on where your contacts originated and what their most recent interaction with you was.... Simple, right?


Lead source - Original is an indication of the FIRST time a contact was created in your instance and once set this value should never be altered.

This allows you to backtrack & identify what the original source was of that data. For example if a list of data was being imported and fields mapped. – One of the fields in your data file should be lead Source - Original.
This should be imported and then mapped into your Lead source - Original field with an update type of ‘only if Blank’


‘Only if Blank’? 

Yes, absolutely, - the reason as indicated above is that this will only write that value into the record if the record does not already have a value in that field. Therefore, if you accidentally upload a list containing some existing contacts (& we all know it happens from time to time) then you will not overwrite the value that was already in that field from when the record was first created. – So essentially you should have 100% of your records with a value in the Lead source - Original field & that should enable you to breakdown exactly the sources ( & volumes) of Lead generation for your instance.


OK, That makes sense wise master, but so what about this Lead Source - Most recent field?

Well conversely Lead Source - Most Recent should of course be updated as well, but updated in every situation, to give a clear reflection of the contact's most recent interaction with your marketing materials.

This should capture the activity they just conducted. – Whether their 1st, or 421st.
Initially it will be the same as Lead source - Original, but as time progresses they will start to diverge, with Lead Source - Original always remaining constant, & Lead Source - Most recent always showing what they did most recently.


Here is a simple article demonstrating how to do this correctly on the processing steps on the back of a form.
How To: Updating Lead Source fields from a Form Submission.




But how granular should it be?

Well that’s up to you really, but essentially it should be detailed enough to categorise your leads in a useful way, but not so detailed that it becomes onerous for you to report on.

if you have a set of fixed values: like web form, Webinar, Tradeshow, Event, Sales, Whitepaper download, etc. then you can run a simple field population report & it will break down the field into those clear distinctions, along with numbers.


Lead SourceCount
Web form7,631


Perhaps you do want to be more granular, - that’s fine too of course, just be mindful that having fewer set values is easier to maintain & you can even use Eloqua to ‘listen’ for invalid values and present them to you in a filter (see below),
so you can readily see that this month you have had 3 records created without the correct values, and you should be able to deduce where they originated in order to educate the person responsible (choking not advocated!).


So why is all this important?

Well it might become relevant if you start to conduct Closed Loop Reporting (CLR), and wish to perform analysis on the amount of your closed leads, - where they originated, and the last interactions they had before they closed.

Case in point, - if your CLR evidences that 40% of your closed leads entered your database after registering at one of your Webinar events, but thereafter downloaded a particular whitepaper before purchasing – well, you can infer two things here.
Firstly to put more money into your webinars as they are generating good quality leads*, but also that you should be pushing leads who come from that source into a campaign to try & forward these important Whitepapers directly to them proactively.

If you can see a winning recipe for sales in your data, then you can use the power of Eloqua to try and replicate that.


*I am aware that other factors are at play here, such as cost per lead etc. (this is a simple explanation though)



Here is a working Example for you to see it in action.

Initially we upload some contacts from an event (along with Lead Source - Original & Lead Source - Most Recent).
Lead Source - Most Recent should always update, Lead source - Original should only update if blank.

The Event in question is a meetup and music Event at a local Cantina in Mos Eisley.


First Name

Last Name



Lead Source - Most recent

Lead Source - Original

Luke S.



JED1 inc.

Event- Cantina (01/01/19)

Event- Cantina (01/01/19)




Falcon Aluminiums

Event- Cantina (01/01/19)

Event- Cantina (01/01/19)




Falcon Aliminiums

Event- Cantina (01/01/19)

Event- Cantina (01/01/19)




Carbonite storage solutions

Event- Cantina (01/01/19)

Event- Cantina (01/01/19)



Head hunter

Force Removals

Event- Cantina (01/01/19)

Event- Cantina (01/01/19)

EmPerorCTODark Side recruitmentEvent- Cantina (01/01/19)Event- Cantina (01/01/19)



As detailed earlier all of these contacts have a common Lead Source - Original & Lead Source - Most Recent. This is expected if they have only had one interaction with you.


Over the next few months there are a number of other interactions involving our demo subjects.


Stan Solo downloads a whitepaper on smartening up scruffy interiors.

Stu Backer watched a webinar on Anger management

Luke Walker Submitted a form to update his details & preferences

Bob Fett clicked through an email with a blind form submit to get information on updated storage.

Em Peror requested a callback (sometime around December 19th 2019 probably!)

Dave Maul was never heard from again.


All of these Changes should be reflected in the Lead Source - Most Recent, but NOT Lead Source – Original, as for all those contacts were created as part of the Cantina (01/01/19) event.
This is where the contact originated so this should never alter as they will only ever originate one time, from one place.


A few Months later the table would have altered like this. – Note that Lead Source – Original has not changed for any of them as that field denotes how they first originally arrived into the contact table. That fact will never alter.


First Name

Last Name



Lead Source - Most recent

Lead Source - Original

Luke S.



JED1 inc.

Re-Engagement (04/05/19)

Event- Cantina (01/01/19)




Falcon Aluminiums

Webinar – Anger Mgmt (11/02/19)

Event- Cantina (01/01/19)




Falcon Aliminiums

Whitepaper – Scuffy int’ (01/03/19)

Event- Cantina (01/01/19)




Carbonite storage solutions

Blind form- Storage (01/04/19)

Event- Cantina (01/01/19)



Head hunter

Force Removals

Event- Cantina (01/01/19)

Event- Cantina (01/01/19)

EmPerorCTODark Side RecruitmentCallback form (12/04/2019)Event- Cantina (01/01/19)


You can see the cell alterations in Yellow (You don't necessarily need to include dates, I've included those just to communicate my point).

What we've started to do here though is get more granular in the recording, allowing us to delve deeper into exactly what communication resonated, but making it much harder to report on.


What is often used is a code, consisting of the details of the email that drove the contact to that resource, something like EM_05_19_UK_Y0DA


EM, denoting Email, then MM_YY, then Country code, then a 3 or 4 letter code for detail.

This code should be added to all links in all emails ( unique to each email), - then if it is catalogued somewhere,  you can refer back to see what codes relate to what emails.


So you might end up with the below, which is complex, but can be traced back to individual emails driving the contacts to forms or other content.


Lead SourceCount



So How do I update those values once they're included in the links?

Well fortunately there are a few techniques you can employ within the Eloqua platform which will help you here, see below for a couple,
but first things first, you must bring balance to your data and you do this by committing to data quality and then tidying up your data sanity. Adding good data onto bad helps no-one.

It is not a small job to get things set right, but it’s much easier to maintain once the effort is in place to solve data sanity.
It’s also important to maintain this rigidly. If you do not, the erroneous values will be back, (and in greater numbers). So you must track the fields and correct errors as they arise.


Want to learn more...?


Read my guide to see how to populate your records with Lead Source values consistently off the back of an Eloqua form.
How To: Updating Lead Source fields from a Form Submission.


And Read my Guide here on using JavaScript / JQuery to capture values on your web pages & pass those into hidden fields.
How To: Using JavaScript / JQuery to update a Hidden Formfield.


And finally read my guide on how to lift rocks whilst standing on your head.
(Just kidding!)



Now, *waves hand* repeat after me,
“This was the article I was looking for”….

“I will commit to better data sanity and reap the rewards”


Very good.

Now Move along please…..




Andy Ball

Eloqua Principal Technical Account Manager,

Oracle Cloud Priority Support.

So all in all, this is a simple process.


You'll need to create a form update Rule then you'll create two processing steps on your form.


First the Form update Rule.


go to Audience > Tools > Form update Rules.


Hit New to create a New one. We'll call ours "copy LS- MR to LS-O"


It's going to operate on the Entity type Contacts and the Data field is Email Address


Now we just create one rule as below:

This copies the value from Lead Source - Most recent Into Lead Source Original. That's all it does.




Now the processing steps.


Obviously we want to Update our Contact table, so we add the Update Contacts - With Form Data step.



There's two ways you can set your value, - either set a static value in the form field so that same value is passed every time,
OR, if the form field will be driven to from various sources, have a hidden field on the form that we populate using JavaScript (see my guide on how to do that)

Either way we map that field to Lead Source - Most Recent

This ensures that for EVERY form submission a relevant Lead Source value is written into the Lead Source - Most Recent field (as it should be, 100% of the time).


We then add a second processing step to utilise our new Form update Rule.


The step we use is 'Update Contacts with Custom Values'.

click the 'Apply shared Update Rule' button to add your Form Update Rule, and set the step to operate conditionally if Lead Source - Original (is Blank)



You could just set it as a one-off processing step to update the field from Lead Source - Most Recent to Lead Source - Original, but by creating a shared rule we can use it on every form!



And that is that,

Lead Source - Most recent will always be set to your value, so will be updated 100% of the time.

Lead Source - Original will grab that value the first time a value is set, but never after that.



I hope that helps.



Andy Ball

Eloqua Principal Technical Account Manager,

Oracle Cloud Priority Support.

The thought of JavaScript & coding in HTML on Lading pages & web pages can often be daunting. But it needn't be,

Here is a short guide on how to use JQuery (a simple JavaScript library) to grab a value from your URL & drop that into a hidden form field ready for form submission.


Example: - your user clicks through to your form at


Note the bit after the .com ?LeadSource=DOIEmail - this is what we call a query string parameter. - it's extra text that wont affect the visit to, but you can use in some way once the visitor arrives.


It is what's called a key value pair. - the key(before the equals sign) is linked to the value ( after the equals sign).

We can string many together with the '&' character.

the '?' character just tells the browser to stop rendering the URL at that point.


What I mean by that is that Is exactly the same as (...go on, try it!)


All of the text this=that&another=one&yetAnother=one&more=data&so=on that occurs after the ? in the URL is ignored. but we can use it upon page visit if we so choose.


So here we go.


In your HTML, within the Head tags (the bits that go <head > .... </head>) you're going to add a reference to JQuery.

We're going to use a Google hosted version as that will always be accessible & it saves us hosting a file & keeping it up to date.


Google libraries can be found here:


The JQuery link looks like this: <script src=""></script>


So we add that between the Head Tags:


JQuery call


<script src=""></script>





Now we add a GetParameters function to do the work for us.


JQuery call + Get URL function.


<script src=""></script>


      $.urlParam = function(name){

    var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);

    if (results==null) {

       return null;


    return decodeURI(results[1]) || 0;





That is going to do the heavy lifting when we ask it to.


Now on our form we have a hidden form field with an ID of LeadSourceFormField - like this: <input name=leadSource id="LeadSourceFormField">

This field will capture the value we supply & we can use this id to target the field with JQuery.


Lastly we're going to add a short script just before the closing </body> tag to run once the page loads, It will look into the URL for our query string parameter & grab the value to put it in the form field:


Call to get Parameter & posting it into the form field


      $( document ).ready(function() {







And that's it!

So that code will run on page load, - scan through the URL for the parameter with id=LeadSource. get the associated value, then put it into the form field with the ID LeadSourceFormField.

When the user submits the form, the hidden value will be submitted for you to track on your Eloqua form & to then post to the Lead Source fields as you see fit.


So now, - going back to our earlier example: - your user clicks through to your form at

If a user clicks through to our form, illustrated above as Google, our new code will capture the value 'DOIEmail' that is associated with the Key LeadSource in our Query String.

We capture that value to post it to Eloqua.


If someone else visits the same page with a different Query string value, like at

The same code will captrue WebinarInvite and that will get posted instead.


I hope that all makes sense, please use the comments if there are follow up questions.


Here is a complete stripped back example of the Entire HTML page for you to examine: (the form is of course simplified for this example)


Example of HTML

<!DOCTYPE html>



    <script src=""></script>


      $.urlParam = function(name){

    var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);

    if (results==null) {

       return null;


    return decodeURI(results[1]) || 0;







      <input name=firstname><br>

      <input name=lasttname><br>

      <input name=emailAddress><br>

      <input name=leadSource id="LeadSourceFormField" type="hidden"><br>

      <button type="submit">Submit</button>





      $( document ).ready(function() {









I hope that helps.



Andy Ball

Eloqua Principal Technical Account Manager,

Oracle Cloud Priority Support.

The responsive builder is a great way for users to build quick and reliable landing pages, with lots of flexibility in structure and templates offered.  It's really easy to use, surprisingly intuitive, and the code output is decent. But it does have its limitations.


There are two tiny things that I would expect to set on any web page: the page title and the shortcut icon, known as a "favicon". These are used in bookmarks, in browser window title bars, and in the case of search engines, the page link text.


Each one is just one line of HTML, and it boggled my mind that neither is available as a standard setting, nor can you use the "Additional Meta Tags" box to add them - both <title> and <link> tags are stripped out when you save.


Fortunately, all is not lost - both of these can be set with one of these workarounds:

  • a Custom Code block - except the favicon does not show up in Chrome
  • a small piece Javascript in the page settings - except the page title doesn't show up in search engines


How to Do It:

Open any landing page created using one of the orangey-pink responsive templates.


... with a Custom Code block

This is the better option if how search engines list your page is important to you. Note that visitors using Chrome will not see your custom icon in their bookmarks or browser window.

  1. Drag the Custom Code content block from the Design Components toolbar to the top of your responsive page.
  2. Click on it to select it and open its editor, and paste in the following code:
<title>Page Title - Site Name</title>
<link rel="shortcut icon" type="image/x-icon" href="" />
  1. Change the title text and favicon link as needed
  2. In the Padding section of the toolbar on the left, set the padding on all sides to 0.
  3. Click "Save"


... with a piece of Javascript

This is the better option if how your visitors see your page is most important to you, and you aren't worried about how search engines will list your page.

  1. Click on the cog icon to open the Landing Page Settings tab, and scroll down to the last section - Code and Tracking.
  2. If you don't already have any custom Javascript added to your page, click on the "Add" button under the "Additional Javascript" box. (Otherwise, it'll say "Edit")
  3. Paste the following code into the popup editor:
window.onload = function(){
    // Set title
    var title = document.createElement('title');
    title.innerHTML = "Page Title - Site Name";
    // Set favicon
    var favicon = document.createElement('link');
    favicon.type = 'image/x-icon';
    favicon.rel = 'shortcut icon';
    favicon.href = '';
  1. Replace the blue text in line 4 with your desired page title, and the blue text in line 10 with your favicon url.
  2. Click "Apply", and save your page.


If you have other custom Javascript which includes a window.onload function call, you will need to combine them - just paste lines 2-11 immediately after the start of your window.onload function.


... with a bit of both!

What if you want your visitors to see your custom icon AND search engines to list your page with a useful page title? You can use both!

  1. Add the Custom Code block as above.
  2. Add the Javascript snippet as above, but delete lines 2-5.


What about Custom HTML landing pages?

I see occasional questions on Topliners about it, so it makes sense to collect all the related information together in one place. HTML landing pages can use the standard HTML tags as in the Custom Code block above, but in the right place in the HTML - inside the <head> tag. No workarounds needed!


Just add the following lines of code inside your page's <head></head> tag, and edit accordingly.

<title>Page Title - Site Name</title>
<link rel="shortcut icon" type="image/x-icon" href="" />



I hope this is useful for others!

Motiva AI's intelligent touchpoint frequency management for Eloqua

One of the key variables in campaign design is how often you send emails. Send too much email too often, and bad things follow.

  • Unsubscribes go up
  • IP, domain, and spam reputation damage
  • Risk to your brand increases, and customer trust erodes.


Not good! But how much is too much email? And for whom?


We're releasing a new smart Frequency Management feature in Motiva AI along with some advanced analytics that help you:


1) Control sending at a global level,

2) override this when you have to on a campaign basis, and

3) understand the response behaviors in your population so you develop a sense of where your tradeoffs are in email send frequency.


To use it, just set a limit for emails in a single week, and Motiva AI will take care of the rest. Whatever you set here will control all Motiva AI intelligent canvas steps. So if you have a stoplight program or other limits in place for existing Eloqua email steps, they won't be affected.


Screen Shot 2019-03-11 at 12.54.51.png

You will also be able to tell Motiva in what priority order to evaluate and execute active campaigns. Drag to sort campaigns into descending order of priority as needed.


Screen Shot 2019-04-08 at 15.14.28.png


Motiva AI can even suggest a reasonable frequency setting based on your contacts' behavior across all campaigns.


Finally, we're noodling on some Motiva Intelligent Analytics to help you understand behavior and frequency tradeoffs from your contacts' history:


Screen Shot 2019-04-26 at 5.32.38 PM.png


This frequency management feature sets the stage for further Motiva AI learning in the future - building on our learning over personalized messaging optimization, segments and audiences, send time, and more. Have a go for yourself here:

Motiva AI Per-Contact Send Time Optimization (STO) for Oracle Eloqua
Happy to announce we've released a new version of Motiva AI that automatically discovers the optimal send time for every contact in your contact db. Previously, we've covered Segment-level STO, which is still available when you're optimizing message variations and doing multivariate testing on the Eloqua canvas. This is a new custom action service and a drop-in replacement for any Eloqua Email step.


Using Motiva's Send Time AI is super easy.


  1. Swap in the Motiva Send Time AI action service for an existing Eloqua Email step on your canvas.
  2. Pick an email asset and any optional configuration settings.
  3. Save and activate.


Screen Shot 2019-01-29 at 09.28.21.png


Motiva AI will run the step for seven days. It works by combining historical activity and live machine learning exploration to learn when to send for each contact. The more you use it, the more Motiva AI learns, and the better response rate.


Also: when you use the Motiva Send Time AI step, you no longer need worry about timezones. The goal is to discover the optimal send time policy regardless of where a contact sits in the world. No more complex, TZ-specific campaign pathways to manage.


In early testing we're seeing clear benefit in every campaign we run. More info is here. You can install the Motiva app here.

Send Time Optimization (STO) Insights with Motiva AI and Eloqua: best and worst times and email delay distributions
We've released two new intelligent insights reports for Eloqua Motiva AI campaigns that help you easily target the best times and understand audience behavioral engagement.


Motiva AI's previous STO intelligence has offered a 24x7 grid description of relative response rates. These are available for each Motiva AI email step on any campaign.


There is now an additional summary chart inserted at the top of every Motiva AI STO insights report that looks like this:


Screen Shot 2018-10-23 at 11.04.26.png


We wanted to make it easier to interpret the fuller grid report (still available) and give you a quick sense of your top three strongest- and weakest-performing slots at a glance.


We've also added a brand new intelligent report for Delay Distribution. Delay Distribution describes the delay between the hour in which you send an email and the time it takes for your target population to open or click on that email. rather than a simple summary, we want to provide you with a fuller picture of what's happening on every Motiva email across the send time restrictions you designate. Here's how that looks:


Screen Shot 2018-10-23 at 11.04.05.png


The inspiration for this came from our users. We realized that the behavioral dynamics for Motiva newsletter optimization campaigns were behaving differently from onboarding and nurture campaigns, and differently from event-driven campaigns.



  • Different segments can show sometimes dramatically different response patterns with the same or similar campaign types
  • Seasonality can matter depending on industry vertical
  • Seniority and role can correlate with responsiveness - apart from overall rate, time-to-response differs
  • Language optimization around calls to action can help drive shorter time-to-response and levels of engagement
  • Does send time even matter, and if so how much?
  • And more


These new features are part of our push towards understanding customer audiences better and giving you the insights you need to take action and improve outreach. Try it out; tell us what you learn. We appreciate your feedback.

*Assuming that you are aware how to create segments.

  1. Create the segment per your business requirements.
  2. Go to Audience Icon >> Tools>>Data Export and Import

3. Click on Data Export >> + sign

4. Go to Export Settings >> and details highlighted in RED (see below snapshot)


5. Add emails addresses under “Notification”, you can add multiple email addresses by using semi colon.


6. Select DATA>> go to all items highlighted in RED(see below snapshot)


7. Hit Save.

8. Go to Overview tab and crosscheck all the details, you can click on RUN NOW to check the report in the inbox of email mentioned in the notification step.


Test the report.




1.       Test the report.

OK, - So you've previously used my 'amazing' guide on Cleaning up Unmapped CDO records, right? (If not, be sure to check it out for a great technique to tidy up your old unmapped CDO records).


Good, - so if you did follow my previous guide you can be assured that your CDO's contain 100% mapped contacts and your Custom Data Objects overall are in great shape.


But Now you're getting GDPR 'right to be forgotten'  requests requiring you to delete contacts, along with all of their associated CDO data. How tricky is that going to be?

After all you have a whole bunch of CDO's, so that's going to take some time and effort to resolve isn't it?


Fortunately, I have the solution you've been looking for.



This guide is going to show you how to use Eloqua's Program canvas to automate this entire process for yourself...


Here's the ingredients you're going to need:


  • One free Contact table field, we'll call this Delete CDO records?
  • A segment which will listen for your above field to have the right 'trigger value'
  • One master Contact Program canvas.
  • One Custom data object Program canvas per Custom Data Object that you have.


and that's it.


so, now we'll put it all together.


The new contact field.


As stated, we're going to call this field:  'Delete CDO records'


For simplicity's sake I'm using a text field, but you could use a checkbox or a picklist if you wanted.

In this instance we'll use a Text field with a default value of N (as in No, don't delete the CDO records).


Here's how I set it up:


This gives us a new field that we can use in our new Segment (which I called the same thing)

This is where we will evaluate if our new field is equal to 'Y' - this will only happen when we choose it to, so initially the count of this segment will clearly be 0



Now to the meat of the programs.


So for the main Contact Program canvas it will have a very simple structure. - each contact is evaluated against to check if they have a record in the CDO. - if so, the associated record is pushed into a CDO program for that CDO, which will delete it.


Here's the flow of my main program:


OK, so let's break it down. - the decision steps basically look at the associated CDO (in this example, CDO1, CDO2, CDO3 etc....)

and it looks for an email address field value in the associated CDO. - If you aren't capturing email address in that record, then any other field which is constant for all records will work fine.


If this is true then we push the associated CDO record into one of the other 'deletion' Custom Object Program canvases that we're about to create.....

This is done by using the Add Linked Record to Program canvas step.


then we rinse & repeat for each CDO, so we have one 'evaluation' and one 'push to program' step for each CDO that we have.


Make your own life easier:
As stated above. you will need one 'deletion' Canvas for each CDO that you have. If you have 120 CDO's then you will need 120 of these programs, so to make your life easier you should first audit your CDO's and delete any that are redundant or no longer required.


Now you should have the framework of your Program a bit like the below, but you cannot configure the Add Linked Record to Program steps until you have actually made those canvases.


The deletion programs.


So the last step we have to do is to create the Custom Object Programs to handle the deletions.


fortunately these are VERY simple and only take a minute or so to build: - this is what they look like.


Very simple. - just create the Program & assign it to the CDO in question ( in my case it was CDO 1 for deletion Test)


Then add a listener, & add one Delete Custom Object Record step. Link the two & you're done. ... Onto the next one.


You can't copy & paste.

If you're thinking of cutting corners here & copying your canvas just to change the associated CDO, think again. - copying the canvas also copies the CDO association!  so you do in fact need to create a new one each time.

Luckily they are very easy to build!

So now you have one of these deletion Custom Object canvases for each of your CDO's so you can go back through your main Contact Program & tie all of the Send Linked Record steps to the correct Custom Object Program.

Don't forget to 'Choose' the right program & the Listener on that Program.


And then that's done.


you can now activate your program.

Now whenever you update the Delete CDO Records field of a contact to Y, it will be captured in the Segment in the next evaluation. thereafter flowing through your program and deleting all CDO records attached to that contact.

Note: Once you configure the segment, it is evaluated on a regular basis based on your configuration. The minimum time between evaluations is 1 day.


So if you have a list of 50 contacts that you are looking to delete from your instance, - you should upload these from an excel sheet with simply two fields - Email address & Delete CDO Record ( the latter will all be the value 'Y').

After the list is uploaded you can sit back & wait for all of the CDO records to be erased. after that ( and only after that), you can delete the contacts themselves. - if you delete them first they won't be able to flow through your contact Program!!



But Does it Work?


In order to test this, I created a simple Proof of concept, then created a Test matrix to highlight that some records in the CDO would be pushed through & some would not. - As you can see from the below image, - it worked exactly as planned.



Good Luck!!



Andy Ball

Eloqua Principal Technical Account Manager,

Oracle Cloud Priority Support.

Assuming that we all are aware of Custom Objects, for more info -

What is Custom Object Services? Custom object record services monitor the changes within a custom object. They run every 15 minutes and are used to automatically trigger one or more actions with your custom object records, such as sending them to a program.

Use Case: You wanted to collect alternate email addresses of few customers via form and would like to send emails to their alternate email address. We all aware that “Email Address” is a system field and submitting a new information via any form will create a new record in Eloqua also, saving the alternate email address in a custom contact field will not help, as we will not be able to send emails to them.

The below steps will help you to create form and collect form data (alternate email address) in a CDO and then send email to that alternate email address via Custom Object Services.


  1. Create a form with default email address and a custom field “alternate email address” with other required fields that you would like to have.
  2. Create a dummy custom Object.
  3. Add form processing steps –

Update Contacts – With Form Data, and

Update Custom Data Object – With Form Data


**Choose the step 2 dummy custom object under “Choose a Custom Object” section in Form Processing Steps.


4. Now, let’s get started with Custom Objects, open you dummy Custom Object, click on Custom Object Record Services and you will notice the below screenshot:

5. Edit the processing steps of “New Data” and “Modified Data” per your requirement.

6. Hit Save and repeat steps add and configure as many processing steps as needed to either service.

7. Return to the main menu for the custom object, and click Save.

** It is important to return to main menu and save to see options to enable those services.


8. Click the drop-down arrow to either service to which you've added steps:

  • Edit Service Actions: you can continue to add, modify or delete the processing steps from the service.
  • Run Service: Instantly run the service to test it.
  • Enable Custom Object Record Service: Enable the service so that it carries out its processing step. There is a 15-minute wait until the first iteration of the service's function occurs.

9. Save and close.

For reports: Click Custom Object Record Services, then select one of the two options:

  • Custom Object Record Service History: Summary of all the changes that have been made to the services
  • Custom Object Record Service Run History: Summary of every instance the service has been run.


For more information on Custom object record service click here -

[If anyone knows a better way of doing this please let me know. I believe they might be changing the limit soon to around 200k but essentially this problem may still exist]




This approach will create a report that is over 65,000 contacts and you can then use row numbering to filter 65,000 records at a time so you are batching your exports within the limit. This will involve multiple exports but you can quickly batch the rows by updating the numbers. I will also add in a prompt as an additional section so users without an Analyzer license can then group the contacts into 65,000 batches without needing assistance from the analyzer user.


If you are doing a mass export of all contacts, you could just add the field "Eloqua Contact ID" instead. As this is for a campaign and the contacts IDs are more random I can't use "Eloqua Contact ID" as a filter




We routinely get asked to export contact level data with lots of email addresses so we easily go over this 65,000 limit. When you hit export it will then just take the first 65,000 contacts only. I can't find a way of doing this to increase the limit but there is a way to make this a little easier by filtering by bands to cover 0-65,000, 65,001 - 130,000 etc. The Pivot view is supposed to support pagination but this is an alternative approach.


When you need to export large volumes of data from Oracle (OBIEE) / Insight to excel for example you are limited by the settings configured by Oracle. It appears if you own the non-Eloqua version you can change the middleware to export more but with the version that they use with Eloqua you don't have access to change this.




You will need an Analyzer license to do this.


> Let's say we have a report that looks like this. There are multiple emails in a massive nurture. We have been asked to show all of the opens by contact so they can do a deeper analysis.



> Go to the "Results" tab and hit the add "New Calculated Measure" icon



> Click on the function icon



> Select the "RCOUNT" function which is for row counting



> Change the expression to 1. So it should be RCOUNT(1) and not RCOUNT(expr)



> You should then see a list of numbers for each row. You can sort to arrange more neatly if needed.





> Save it

> Return to the "Criteria" tab and create and filter on the RCOUNT column



> Add in your banding so it can operate between two values. This must be a maximum of 65,000 records because that is the maximum number that can be exported (at present Jun-18)



> You should end up with this.



> When you go to the "Results" tab you will now have the first 65,000 rows only



> If you want to export the next batch of contacts (65,001 - 130,000) you can then update the filter and run it again for the next batch.



Additional Section


> If you want to make this functionality available to other users that don't have an Analyzer license you can add it as a prompt.



> Select the green plus icon



> Then double click on the new prompt and update per below. Note I've added a custom label so the end user can see something else other than "RCOUNT" which might not make much sense for them. The description will only show as you hover over the prompt.



> The users should then see a prompt box like this when they are running the report



Hope that helps

Use case: Let us say you wanted to have phone numbers to be in the following format without spaces and “00” or “+” in the starting of the phone number.

  1. Open your Program Canvas or Campaign Canvas and drag and drop CWM app, click on configuration.
  2. Assuming you are aware of CWM app, select Action as “RegEx Replace” and enter below code.


Find: \D ->it will remove all the spaces, “-“from the phone number.

Replace: Blank


3. Now, select Action as “RegEx Replace” again and enter below code:

Find: ^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$

Replace: 00$1$2$3$4 or +$1$2$3$4



4. Test your configuration: You will notice in first example- input of “+1231224543” with output of “001231224543”, and input of “123 456-1717” with output of “001234561717”.


** Please try it in your sandbox first.


** Need more information on Contact Washing Machine App? Click below Oracle Help Centre doc on what is Contact Washing Machine app, how to download/install it and it’s actions -



Hope this is helpful.



Use case: Let’s say (see below snapshot) you have customized - “Email Analysis by Email Group” report per your use case and now you would like to customize the secondary “Total Clickthroughs by Contact” report to be replaced with the new, custom report you have created with specific contacts fields.

Let us get started:

As stated, I would be taking “Email Analysis Overview” report as an example, so when you click on any out of box report, analyzer license allows you to customize the report. Hence, Analyzer license is must in this case.


  1. Open any out of box report – let’s say,  “Email Analysis by Email Group” report, when you click on any metrics, let’s say “ Total Clickthroughs” it takes you to a drilled down (secondary) out of box report “Email Analysis by Email Group - Total Clickthroughs” which tells you the contact details like – email address, first name and others. We all know we can customize “Email Analysis by Email Group” report, now you can actually customize the later (secondary or drilled down) report. So, that any user click on your saved report and clicks on drilled down report, it will actually takes the user to customized drilled down report.

Below are the steps to customize the drill down report:

  1. Open any out of box/custom report and “save as” in any of the folder. Let us say the report is “Email Analysis by Email Group”.
  2. Open the drill down report and “save as” it as well. For Example – “Email Analysis by Email Group - Total Clickthroughs”
  3. Click on the gear icon of the attribute you want to update, click on “column properties” of “Email Analysis by Email Group” report.

   4. Click on “Interaction” ->”+”->”Actionlinks”:


    5. Click on “Navigate to BI Content”:

    6. Select your secondary or drill down report and save.

    7. Hit Results on primary report and you will notice that on clicking the “Total Clickthroughs” you will be getting customized secondary report.


Hope that is helpful.

Filter Blog

By date: By tag: