Having difficulties with OfflineDataUpload Python Suds v201708

69 views
Skip to first unread message

Steve Wilhelm

unread,
Nov 8, 2017, 1:03:14 AM11/8/17
to AdWords API Forum
We are trying to add user transactions to our Adwords campaigns. 

We are using the Python Suds API version v201708

Here is the error we are receiving

suds.WebFault: Server raised fault: 'Cannot construct an instance of com.google.ads.api.services.datax.offlinedataupload.UploadMetadata because it is abstract.  You are probably missing an @Uses annotation while invoking public abstract com.google.ads.api.services.datax.offlinedataupload.OfflineDataUploadReturnValue ...'



Any advice or a working example would be appreciated.

- Steve W.

The XML that was created by the API is:

<?xml version="1.0" encoding="UTF-8"?>
   <SOAP-ENV:Header>
      <tns:RequestHeader>
         <tns:clientCustomerId xmlns:tns="https://adwords.google.com/api/adwords/cm/v201708">***-***-****</tns:clientCustomerId>
         <tns:developerToken xmlns:tns="https://adwords.google.com/api/adwords/cm/v201708">*********************</tns:developerToken>
         <tns:userAgent xmlns:tns="https://adwords.google.com/api/adwords/cm/v201708">Euclid AdAdmin (AwApi-Python, googleads/8.0.0, Python/2.7.10)</tns:userAgent>
         <tns:validateOnly xmlns:tns="https://adwords.google.com/api/adwords/cm/v201708">false</tns:validateOnly>
         <tns:partialFailure xmlns:tns="https://adwords.google.com/api/adwords/cm/v201708">false</tns:partialFailure>
      </tns:RequestHeader>
   </SOAP-ENV:Header>
   <ns0:Body>
      <ns2:mutate>
         <ns2:operations>
            <ns1:operator>ADD</ns1:operator>
            <ns2:operand>
               <ns2:uploadId>123</ns2:uploadId>
               <ns2:externalUploadId>456</ns2:externalUploadId>
               <ns2:uploadType>STORE_SALES_UPLOAD_THIRD_PARTY</ns2:uploadType>
               <ns2:uploadStatus/>
               <ns2:uploadMetadata xsi:type="ns2:ThirdPartyUploadMetadata">
                  <ns2:loyaltyRate>0.0</ns2:loyaltyRate>
                  <ns2:transactionUploadRate>0.0</ns2:transactionUploadRate>
                  <ns2:advertiserUploadTime>01:05:00</ns2:advertiserUploadTime>
                  <ns2:validTransactionRate>0.0</ns2:validTransactionRate>
                  <ns2:partnerMatchRate>0.0</ns2:partnerMatchRate>
                  <ns2:partnerUploadRate>0.0</ns2:partnerUploadRate>
                  <ns2:bridgeMapVersionId>bridgeId123</ns2:bridgeMapVersionId>
                  <ns2:partnerId>partnerId123</ns2:partnerId>
               </ns2:uploadMetadata>
               <ns2:offlineDataList>
                  <ns2:userIdentifiers>
                     <ns2:userIdentifierType>EXTERNAL_USER_ID</ns2:userIdentifierType>
                     <ns2:value>id123</ns2:value>
                  </ns2:userIdentifiers>
                  <ns2:transactionTime>2017-10-31 17:30:00-08:00</ns2:transactionTime>
                  <ns2:transactionAmount>0</ns2:transactionAmount>
                  <ns2:conversionName></ns2:conversionName>
               </ns2:offlineDataList>
               <ns2:failureReason/>
            </ns2:operand>
         </ns2:operations>
      </ns2:mutate>
   </ns0:Body>
</SOAP-ENV:Envelope>


and here is the code

import datetime
from googleads import adwords
from googleads import oauth2
from httplib2 import Http
from oauth2client import client
import logging
import constants

logging.getLogger('suds.client').setLevel(logging.DEBUG)
logging.getLogger('suds.transport').setLevel(logging.DEBUG) # MUST BE THIS?
logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG)
logging.getLogger('suds.wsdl').setLevel(logging.DEBUG)
logging.getLogger('suds.resolver').setLevel(logging.DEBUG)
logging.getLogger('suds.xsd.query').setLevel(logging.DEBUG)
logging.getLogger('suds.xsd.basic').setLevel(logging.DEBUG)
logging.getLogger('suds.binding.marshaller').setLevel(logging.DEBUG)



# Authorization

credentials = client.OAuth2Credentials(
    None, constants.CLIENT_ID, constants.CLIENT_SECRET, constants.REFRESH_TOKEN,
    datetime.datetime(2049, 1, 1, 12), constants.GOOGLE_OAUTH2_ENDPOINT,
    constants.USER_AGENT)
logging.warning(credentials)

# Adword Client

adwords_client = adwords.AdWordsClient.LoadFromStorage(constants.GOOGLEADS_YAML)
# logging.warning(adwords_client)

adwords_client.SetClientCustomerId(constants.CLIENT_CUSTOMER_ID)
# adwords_client.SetClientCustomerId(constants.POST_VISITS_AS_ZERO_DOLLAR_TRANSACTIONS_ACCOUNT_ID)
# logging.warning(adwords_client)

# OfflineDataUpload Operations
offline_data_upload_service = adwords_client.GetService('OfflineDataUploadService', version=constants.VERSION)

# User suds to make OfflineDataUploadService calls
suds_client = offline_data_upload_service.suds_client


# create a user identifier
user_identifier = suds_client.factory.create('UserIdentifier')
user_identifier.userIdentifierType = 'EXTERNAL_USER_ID'
user_identifier.value = 'id123'

# create a store sales transaction
store_sales_transaction = suds_client.factory.create('StoreSalesTransaction')
store_sales_transaction.userIdentifiers = [user_identifier]
store_sales_transaction.transactionTime = '2017-10-31 17:30:00-08:00'
store_sales_transaction.transactionAmount = 0
store_sales_transaction.conversionName = ''


# create 3rd party upload metadata
third_party_upload_metadata = suds_client.factory.create('ThirdPartyUploadMetadata')
third_party_upload_metadata.loyaltyRate = 0.0
third_party_upload_metadata.transactionUploadRate = 0.0
third_party_upload_metadata.advertiserUploadTime = '01:05:00'
third_party_upload_metadata.validTransactionRate = '0.0'
third_party_upload_metadata.partnerMatchRate = '0.0'
third_party_upload_metadata.partnerUploadRate = '0.0'
third_party_upload_metadata.bridgeMapVersionId = 'bridgeId123'
third_party_upload_metadata.partnerId = 'partnerId123'


offline_data_upload = suds_client.factory.create('OfflineDataUpload')
offline_data_upload.uploadId = 123
offline_data_upload.externalUploadId = 456
offline_data_upload.uploadType = 'STORE_SALES_UPLOAD_THIRD_PARTY'
offline_data_upload.uploadMetadata = third_party_upload_metadata
offline_data_upload.offlineDataList = [store_sales_transaction]


operation = suds_client.factory.create('OfflineDataUploadOperation')
operation.operator = 'ADD'
operation.operand = offline_data_upload

# The service object returned from the client.GetService() call accepts suds
# objects and will set the SOAP and HTTP headers for you.
response = offline_data_upload_service.mutate([operation])
logging.warning(response)
logging.warning(suds_client.last_sent())
logging.warning(suds_client.last_received())


Vincent Racaza (AdWords API Team)

unread,
Nov 8, 2017, 2:02:19 AM11/8/17
to AdWords API Forum
Hi Steve,

Based on your SOAP request, it seems that there is something wrong on how you construct the UploadMetadata object. Below is the correct SOAP request snippet with this object:

<operations>
     
<ns7:operator xmlns:ns7="https://adwords.google.com/api/adwords/cm/v201710">ADD</ns7:operator>
     
<operand>
         
<externalUploadId>XXXX</externalUploadId>
         
<uploadType>STORE_SALES_UPLOAD_FIRST_PARTY</uploadType>
         
<uploadMetadata>
             
<StoreSalesUploadCommonMetadata xmlns:ns8="https://adwords.google.com/api/adwords/rm/v201710" xsi:type="ns8:ThirdPartyUploadMetadata">
                 
<ns8:loyaltyRate>0.0</ns8:loyaltyRate>
                 
<ns8:transactionUploadRate>0.0</ns8:transactionUploadRate>
             
</StoreSalesUploadCommonMetadata>
       
 </uploadMetadata>

Basically, the ThirdPartyUploadMetadata is a type of StoreSalesUploadCommonMetadata, so you need to create an object of type StoreSalesUploadCommonMetadata with an instance of ThirdPartyUploadMetadata. Apologies as I am not an expert in Python so I'll just provide a sample code snippet in Java so you can check how the object should be constructed:

  OfflineDataUpload offlineDataUpload = new OfflineDataUpload();
  offlineDataUpload
.setExternalUploadId(externalUploadId);
  offlineDataUpload
.setOfflineDataList(
  offlineDataList
.toArray(new OfflineData[offlineDataList.size()]));

  offlineDataUpload
.setUploadType(OfflineDataUploadType.STORE_SALES_UPLOAD_FIRST_PARTY);
 
UploadMetadata uploadMetadata = new UploadMetadata();
 
StoreSalesUploadCommonMetadata store = new ThirdPartyUploadMetadata();

 
  store
.setLoyaltyRate(0.0);
  store
.setTransactionUploadRate(0.0);
   
  uploadMetadata
.setStoreSalesUploadCommonMetadata(store);
   
  offlineDataUpload
.setUploadMetadata(uploadMetadata);

Kindly do the suggestion first and let me know if the issue persists. If it persists, then kindly provide your SOAP request and response logs via Reply privately to author option.

Thanks,
Vincent
AdWords API Team
Reply all
Reply to author
Forward
0 new messages