Getting started with the Omniture APIs using Visual Studio 2010 (WCF)

If I had to pick one development platform as the most awkward for working with the Omniture web services it has to be Microsoft’s .NET. With Visual Studio 2005 it wasn’t too bad. You could simply leverage the WSE 3.0 extension and you were in business. But in Visual Studio 2010, WSE has been deprecated in favor of WCF, and unfortunately WCF doesn’t play nicely with the Password Digest authentication method used by the Omniture web services.

Microsoft declares… “B1102 WCF never emits Nonce and Created sub-elements of the UsernameToken.”

This is a problem since the Omniture authentication requires both the Nonce and Created elements.

Luckily, talented Microsoft developers, like ASzego, have come to the rescue and have tweaked the WCF stack to solve the problem. See ASzego’s description of the problem and his solution here.

I’ve taken this code and packaged it up into a DLL file. I’ve also generated a second DLL file that contains the code produced from .NETs digestion of the Omniture WSDL. This code also needed a bit of tweaking which I won’t go into here. Both of these DLL files have been added to the code gallery here.

What we have below is a getting started guide for putting together a quick VS2010 (C#) project that utilizes these two DLL files to make a successful request with the Omniture APIs.

Step 1: Create new Console application

Step 2: Copy the UsernameTokenLibrary.dll and OmnitureAPI.dll into the project. See DLLs.

Step 3: Add each dll file as a reference.

Step 4: Add “System.ServiceModel” as a reference under the “.NET” tab.

Step 5: Add the following code into the Main method…

OmnitureWebServicePortTypeClient client =
OmnitureWebServicePortTypeClient.getClient("[api username]", "[api secret]", "");
int tokenCount = client.CompanyGetTokenCount();
Console.ReadLine(); //this is just to pause and observe the result when debugging

Step 6: Replace the first to arguments to the “getClient” method with your actual API username and API secret. Also, the third (endpoint) parameter may need to be adjusted based on which data center your account is tied to.

Step 7: Add the following “using” statements to the top of the file…

using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using Microsoft.ServiceModel.Samples.CustomToken;
using Adobe.OmnitureAPI;

Step 8: Run the application – observe the token count in the console window.

Finally, I must admit that I have very little experience with .NET and Visual Studio. The time I have spent is only due to the several desperate pleas I’ve seen for help in this area. If you have a better solution for using the Omniture APIs in VS 2010 I would love to hear it.

Please post your feedback.



Thanks for posting this. I implemented your solution and I am getting an error on the CompanyGetTokenCount method call: "Element 'faultstring' with namespace name '' was not found. Line 6, position 117." System.Exception {System.Xml.XmlException} Any idea how I can resolve this? Thanks.

Hi skruger, Unfortunately the exception you are seeing isn't revealing the real issue. I'm guessing that one of more of the parameters that you are specifying for the "getClient" call is incorrect. One way to see the actual SOAP fault that is being returned is to direct your requests through a packet monitoring program (like Charles) with some proxy settings. This allows you to see the actual SOAP messages going back and forth. I did this using the following three steps... 1- add the proxy settings in your application config file 2- handle the Certificate validation issue with a line of code in the top of your main method like this... System.Net.ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(customXertificateValidation); 3- the above line of code needs this method defined for your class... public static bool customXertificateValidation(object sender, System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors error) { return true; } By doing the above I was able to look in my Charles application and see that the actual faultString was "Invalid login." (i gave my app some invalid credentials to force this error). If you do the same you should be able to see what the real problem is. BTW - if anyone has an easier way to see the actual requests going across the wire I'd love to know about it. Hope that helps. -Sean

Hi Sean,greate help ! By the way , is possible i can donwload the full souce for this two library ? Thanks.

The source for these libraries is now available with the DLLs.

Hi Sgubler, Do you have any experience with connecting to Omniture APIs using Business Objects? We want to connect Omniture to our Data Warehouse and would love some advice.

Sorry Meghan. I have no experience with this Business Objects, however if you don't mind I'd like to reach out to you directly and ask a few questions about your use case because we are interested in making the Online Marketing Suite data easy to work with using the popular data integration platforms. -Sean

Hi Sean, i only get one file from link " " . Is it something wrong ? Thanks

You need two DLL files. Both can be found here as separate downloads. The .zip files contain the source code for these DLLs. The only contains a single file. The other source code for the UsernameTokenLibrary.dll file is in a separate zip file.

You legend! I spent hours trying to get this working and got nowhere. Thanks!

Hi Sean, i follow your solution and get error too, can you please give me some advise. Attach is my "Program.cs" Here is the error details:

Attachments: to download.

This was a real time saver. Thanks

It work fine! Thanks sgubler then i have a question , i create a reportDescription like this : reportDescription description = new reportDescription (); description.dateFrom = "2011-07-10"; description.dateTo = "2011-07-16"; description.elements = new reportDefinitionElement [2] { new reportDefinitionElement(){ id="searchEngineKeyword", classification="searchEngine", top=100 }, new reportDefinitionElement(){ id="searchEngineKeyword", top=100 } }; description.metrics = new reportDefinitionMetric [1] { new reportDefinitionMetric(){ id="visits" } }; description.reportSuiteID = report.rsid; description.sortBy = "visits"; I want breakdown by search keyword , but i got the status is failed and the error code is '5024' , message is 'Invalid element' Am i wrong ? or i need setup some thing in my report suite ? Thanks sgubler.

Polomak - try doing your elements like this, first element id should be "searchEngine" and no "classification" needed... description.elements = new reportDefinitionElement [2] { new reportDefinitionElement(){ id="searchEngine", top=100 }, new reportDefinitionElement(){ id="searchEngineKeyword", top=100 } };

Great! But when i try description.elements = new reportDefinitionElement [1] { new reportDefinitionElement(){ id="searchEngine", top=100 } }; searchEngine only return 8 results, try description.elements = new reportDefinitionElement [1] { new reportDefinitionElement(){ id="searchEngineKeyword", top=100 } }; searchEngineKeyword only then return 51 result , but when i try both like your suggestion then return 0 result. I try was success on Omniture website Element "searchEngine" then breakdown by "searchEngineKeyword". Do you have any suggestion,sgubler ? Did i miss some thing ? or i can send you detail by email ? Thanks reply.

Polomak - you'll want to reach out to the SiteCatalyst Account Manager for your organization and have them check that the appropriate Traffic Sources Sub-relations are enabled for your report suite. I'm guessing they are not which would explain the results you are seeing. -Sean

Hi,sgubler you are so enthusiastic! I am the pre-sale analysis man for my organization and responsible for assess the integration between our system and Omniture SiteCatalyst. When i test the Web service Enterprise API through the sanbox and i have two questions as below : 1. Can we set up a web service user account that only can access few report suite? report element : searchEngineKeyword,searchEngine, eVar# report metric : visits,averageTimeSpentOnSite, Single Access,Entries. 2. Bounce Rate =Single Access/Entries , so we can get the avg time on site and bounce rate just from SiteCatalyst now ? We need to know these results before we decide to use Omniture service. Since we can not get the confirm from our consultant. I am really appreciate any assistance you can provide us on this, Many thanks.

Hi Chris.Lee - since it doesn't really relate directly to this post and since it is much easier to format messages in the "Forum" area of this site, could you please post these questions in the "Forum" area? I (or others) should be able to better answer them there.

Hi, Has anyone got this working with a larger number of rows? How did you make it work? When I increase intResultsToGet to, say, 1000 I get this error "The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element". As the Binding class (in the getClient method in Reference.cs) has no MaxReceivedMessageSize property I have tried substituting it for BasicHttpBinding but can't get that to authenticate with the API. Great work sgubler, this has been really helpful so far. Nick

Nick... thanks for the feedback. This is another one where I would recommend starting a forum thread with more details on the issue. Even share some of the key parts of your code. This will improve your chance of getting the help you need.

Hi Nick ,Please try add these code in "BingHelper" below this line HttpsTransportBindingElement httpsTransport = new HttpsTransportBindingElement (); //Set the MaxReceivedMessageSize httpsTransport.MaxBufferPoolSize = int.MaxValue; httpsTransport.MaxBufferSize = int.MaxValue; httpsTransport.MaxReceivedMessageSize = int.MaxValue;

Thank you Chris, you were spot on. I was debugging against the compiled DLL. It was my inexperience with using someone else's libraries showing through, once I reverted to the source I changed the method as described.

Hi, i try to use Omniture wsdl with WCF and VS2010. The link for using wcf is really usefull, but i found some problems... I download wsdl from web , because ( i think ) wsdl used in seems to be different and problem start : i try to convert wsdl with vs tool , svcutil.exe and also with wsdl.exe, but with no success, i always get rpc error. Analizing the output i saw this warning [// CODEGEN: Generating message contract since the wrapper name CodeManager.DeleteCodeArchive) of message CodeManager.DeleteCodeArchiveRequest does not match the default value (CodeManagerDeleteCodeArchive)] for all entries. So i try to modify the wsdl to bypass this conversion problem and it works, i also add some line of code to use it throught proxy that requires authentication, but now i have a problem with buffer size , like Whiteleyn. I try to modify settings in app.config (maxReceivedMessageSize ecc.... ), but when i try to retrive data from DataWarehouseGet.GeportData (wsdl entry) always receive error about [ "The maximum message size quota for incoming messages (65536)......] . Do anyone have some suggestion ? Thank you !

Hi, excuse me, i read with attention Chris.Lee answer about buffer problem, and your snippet work , great, thank you. But i have another problem, the same that i got same time ago using old reference method ( wsdl.exe instead of wcf ) After send DataWarehouse.GetReportData, the program tries to parse response and return this error : The specified type was not recognized: name='data_warehouse_report_row', namespace='', at . If you have some advice , please let me know. thank you

Chris, I followed your advice in modifying the three properties of httpsTransport in BindingHelper.cs. Unfortunately, I am now getting an error that the SOAP response can't be deserialized when calling the ReportSuiteGetSettings method. Has anyone else run into this? Thanks Matt

Hi Sean , I have Followed the Instruction which is given above but while running my programme i met the exception below Exception: There was no endpoint listening at that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details. My code: OmnitureWebServicePortTypeClient client = OmnitureWebServicePortTypeClient.getClient("username", "secret", ""); int tokenCount = client.CompanyGetTokenCount(); Console.WriteLine(tokenCount); Console.ReadLine(); can you help me to resolve this issue. Thanks: Suresh

Hi Suresh, you can use fiddler (or similar ) to inspect your request and see if someting is wrong ( and also post the request to check it )

Hi Matt , I very sure this is will be another exception. Sorry I don't know the problem much without any details ,but i suggest you try to modify the encoding setting in BindingHelper.cs "TextMessageEncodingBindingElement textBindingElement = new TextMessageEncodingBindingElement ( MessageVersion.Soap11, new UTF8Encoding ( false, false ) );" WCF is very powerful . You can extend the IClientMessageFormatter,IDispatchMessageFormatter,MessageEncoder, on .That will very convenient on value monitor and debug . I suggest starting a forum thread to chat about this library.

Hello, I have tried using this post to create application and to request omniture API but its not working for me. the build gets done successfully but after that I get following error. "Could not load file or assembly 'OmnitureAPI, Version=, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified." Please help me with this issue.

I just made a very minor update to this post so that it is current with the new 1.3 version of the API.

Hi sgubler, I have been creating an application to consume the Omniture API and I have been getting the same error as the first comment. After using a packet monitoring program I received the error "Could not establish trust relationship for the SSL/TLS secure channel with authority ''." Along with this the certificate validation method receives the status information as "A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider."

My guess it has something to with my credentials however, when I look into the marketing suite portal the username and shared secret is correct. Am I missing something is setting up something?

Last sentence sounded horrible, " Am I missing something or did I set up something wrong?" ;)

Hi guys,

I know the subject might be a bit old but I just run into the same problem as suresh because of our internal proxy server.

I found a work around that seems to work, after decompiling the OmnitureAPI DLL, I have copied the code that creates and returns the client object, but I have added one parameter to the HttpsTransportBindingElement object.

I have attached my helper class so you guys can test it.

Attachments: to download.


we are upgrading from SQL 2005 to 2012 and trying to convert my API calls to WCF. i have registered both dll's to GAC using strong name (adding it as reference was giving me error for some reason) and i can even see using gacutil -v that they are strongly named yet i am getting error on "UsernameTokenLibrary" complaining that it not strongly named. any ides?

below is the error that i am getting

"Could not load file or assembly 'UsernameTokenLibrary, Version=, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)"

i have windows 7 64 bit installed and using .NET framework 4

any ides how i can resolve this issue?

also forgot to mention that i am using VS 2010 (also called SQL server data tools)

hi,I want to get an hourly report about half year,it seems stack overflow.error is looks like below,looking forward to your help.
The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.

Use the following:
var httpsTransportBindingElement = new HttpsTransportBindingElement
UseDefaultWebProxy = false,
MaxReceivedMessageSize = 2147483647

Or use this DLL instead:

1) Sean you rock
2) For those who are having trouble
-I highly recommend leaving charles open. I was able to get a better error message.. "invalid login"
-It turns out my login was fine but my endpoint was not! I opened the wsdl in notepad++ and searched for "1.3" and found my end is "" instead of ""
-This made all the difference!! Now it works.

Hope that helps someone.


Thanks for this, you've saved me a lot of frustration with getting this to work for a BI project we're starting to work on.

I do have one problem holding me back still though - it appears that specifying the rd.segment_id doesn't have an effect on the returned data from sc:

        // Define the report
        reportDescription rd = new reportDescription();
        rd.reportSuiteID = "tasovereignprod"; = "2013-4-1";

        rd.metrics = new reportDefinitionMetric[3];
        rd.metrics[0] = new reportDefinitionMetric();
        rd.metrics[0].id = "visitors";
        rd.metrics[1] = new reportDefinitionMetric();
        rd.metrics[1].id = "pageviews";
        rd.metrics[2] = new reportDefinitionMetric();
        rd.metrics[2].id = "visits";

        rd.elements = new reportDefinitionElement[1];
        rd.elements[0] = new reportDefinitionElement();
        rd.elements[0].id = "evar6";
        rd.locale = reportDefinitionLocale.en_US;

        // Restrict to "Exclude US Direct Entry Visitors" segment
        rd.segment_id = "dw:209211";

Whatever I specify for the segment id (as returned from the API explorer), the results are the same and the segment is not applied to the report.

Anyone have any ideas? It's driving me mental.


I am new to Omniture and have been assigned to create a client that we can somehow schedule to to send request to Omniture Datawarehouse to run the report and FTP the results to us. I am trying to figure out how to do this using C# and also wondering the reason behind using WCF. I was thinking of creating a console application that will send the request and also setup a SQL Agent job to run the console application once a week.

Your help in understanding the role of WCF and also getting started with console application will be really appreciated.

Syed Zaidi

Following up on the first comment for the error "Element 'faultstring' with namespace name '' was not found". Why doesn't the API library throw an exception with the actual faulstring message? It sounds more like the library doesn't know how to handle error responses from the server. With automated processes we need to be able to log the specific error messages. Right now it appears the only way to get the real error message is to open up Fiddler and recreate the issue to monitor the traffic going back and forth to capture the server response.

@SyedZaidi - that is exactly what I'm going to be doing as well.

Did you get your project up and running and if so did you follow the technique laid out above by Sean?

I'm also wondering if I should now be using the 1.4 version of the API?

Thanks for any info!

Hi Sean,

Are the latest dll files available for supporting API 1.4 version?


Hi Sean,

We have been using SSIS 2012(Visual studio) to make API calls and everything works fine with API 1.3. But now we need to migrate to API 1.4 since the segments created after the update release doesn't appear in API 1.3.

I have converted API 1.4 wsdl to dll file and also successfully registered it using Gacutil.exe. But I am not able to figure out that how do I authenticate myself in API 1.4? for example we are using the following code to authenticate in API 1.3.

OmnitureWebServicePortTypeClient client =
OmnitureWebServicePortTypeClient.getClient("[api username]", "[api secret]", "");

But I couldn't find OmnitureWebServicePortTypeClient class in API 1.4. Do you know how do I resolve this?



Just found out that AdobeAnalyticsServicePortTypeClient class available in API 1.4. So I have replaced the class OmnitureWebServicePortTypeClient with AdobeAnalyticsServicePortTypeClient But still I am not able to create the object of it. I am getting below errors:

  1. The communication object, System.ServiceModel.ChannelFactory`1[AdobeAnalyticsServicePortType], cannot be used for communication because it is in the Faulted state
  2. RPC Message SegmentsDeleteRequest in operation SegmentsDelete has an invalid body name Segments.Delete. It must be SegmentsDelete

Here is the my main program and Client Helper Class:

--Main Program

Imports System
Imports System.Data
Imports System.Text
Imports System.Xml
Imports System.Security.Cryptography.X509Certificates
Imports System.IO
Imports System.Xml.Serialization
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.ServiceModel
Imports System.ServiceModel.Description
Imports System.ServiceModel.Channels
Imports Microsoft.ServiceModel.Samples.CustomToken

Public Sub Main()

Dim ws As AdobeAnalyticsServicePortTypeClient = adobe.ClientHelper.GetClient("UserName","Secret", "")

Dim Seglist(1) As String
Seglist(0) = "ReportSuit_ID"

Dim Segmentlst1(1000) As report_suite_segments
For j As Int32 = 0 To 1000
    Segmentlst1(j) = New report_suite_segments

    Segmentlst1 = ws.ReportSuiteGetSegments(Seglist)

Catch ex As CommunicationException
    Throw ex

End Try

Dts.TaskResult = ScriptResults.Success
End Sub

End Class

--Client Helper Class

Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Description
Imports System.Text
Imports Microsoft.ServiceModel.Samples.CustomToken
Imports ScriptTask_ed2d8ee80c8c45f58ec23cd034536676.ServiceReference1

Namespace adobe
Public NotInheritable Class ClientHelper
Private Sub New()
End Sub
Public Shared Function GetClient(username As String, secret As String, endpoint As String) As AdobeAnalyticsServicePortTypeClient

        Dim httpsTransportBindingElement As New HttpsTransportBindingElement()
        httpsTransportBindingElement.MaxBufferPoolSize = Integer.MaxValue
        httpsTransportBindingElement.MaxBufferSize = Integer.MaxValue
        httpsTransportBindingElement.MaxReceivedMessageSize = Integer.MaxValue
        httpsTransportBindingElement.UseDefaultWebProxy = False

        ' Parameter added to make it work through a proxy
        Dim transportSecurityBindingElement As New TransportSecurityBindingElement()
        transportSecurityBindingElement.EndpointSupportingTokenParameters.SignedEncrypted.Add(New UsernameTokenParameters())
        transportSecurityBindingElement.IncludeTimestamp = False
        Dim textMessageEncodingBindingElement As New TextMessageEncodingBindingElement(MessageVersion.Soap11, Encoding.UTF8)
        Dim bindingElementArray As BindingElement() = New BindingElement(2) {}
        bindingElementArray(0) = transportSecurityBindingElement
        bindingElementArray(1) = textMessageEncodingBindingElement
        bindingElementArray(2) = httpsTransportBindingElement

        Dim customBinding As Binding = New CustomBinding(bindingElementArray)
        Dim binding As Binding = customBinding
        Dim endpointAddress As New EndpointAddress(endpoint)
        Dim usernameClientCredential As New UsernameClientCredentials(New UsernameInfo(username, secret))

        Dim adobeanalyticsserviceporttypeclient As AdobeAnalyticsServicePortTypeClient
        Dim AdobeAnalyticsServicePortTypeClient1 As AdobeAnalyticsServicePortTypeClient
        adobeanalyticsserviceporttypeclient = New AdobeAnalyticsServicePortTypeClient(binding, endpointAddress)
        AdobeAnalyticsServicePortTypeClient1 = adobeanalyticsserviceporttypeclient

        Return AdobeAnalyticsServicePortTypeClient1

    End Function
End Class

End Namespace

Anyone have any ideas? It's driving me mental.


This has been a great help but I get an error calling client.CompanyGetTokenCount() :
"The operation 'SocialGetPropertiesListAsync' could not be loaded because it has a parameter or return type of type System.ServiceModel.Channels.Message or a type that has MessageContractAttribute and other parameters of different types. When using System.ServiceModel.Channels.Message or types with MessageContractAttribute, the method must not use any other types of parameters."
I am unfamiliar with system.servicemodel and a bit stuck...
so far I just have:

namespace OmnitureAPI
class Program
static void Main(string[] args)
//String strLine = "Tst";
//Console.WriteLine("{0}", strLine);
//strLine = Console.ReadLine();
OmnitureWebServicePortTypeClient client = OmnitureWebServicePortTypeClient.getClient("xxxx", "yyyy", "");

       int tokenCount =  client.CompanyGetTokenCount();
        Console.ReadLine(); //this is just to pause and observe the result when debugging


I couldn't get a reference to work to the omnitureapi.dll however I tried so have included the namespace Adobe.OmnitureAPI definition in the program.cs directly. The usernametokenlibrary.dll appears to reference fine...

any help in getting round this gratefuly received.

Must be logged in to comment. now to comment!