Martialdelastic / google-api-adwords-php

Automatically exported from code.google.com/p/google-api-adwords-php
Apache License 2.0
0 stars 0 forks source link

ManualCPCAdGroupCriterionBids malfunctioning while MaxCPC value is 16.08 #18

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
I am getting BID_TOO_MANY_FRACTIONAL_DIGITS error message while the MaxCPC
value is 16.08. It is strange that for other MaxCPC value the code is
working fine. 

I have seen that while the value of MaxCPC given as 16.08, the SOAP request
showing it as 16079999.

Here is the PHP code,

$adGroupCriteriaService = $this->GetAdGroupCriterionService();

      $adGroupId = (float) $adGroupId;
      $criterionId = (float) $keyWordId;
      $newMaxCpc = 16.08;

      // Create base class criterion to avoid setting keyword and placement
specific fields.
      $criterion = new Criterion();
      $criterion->id = $criterionId;

      // Create ad group criterion.
      $adGroupCriterion = new BiddableAdGroupCriterion();
      $adGroupCriterion->adGroupId = $adGroupId;
      $adGroupCriterion->criterion = new Criterion($criterionId);

      // Create bids.
      $bids = new ManualCPCAdGroupCriterionBids();

      $bids->maxCpc = new Bid(new Money($newMaxCpc * 1000000));
      $adGroupCriterion->bids = $bids;

      // Create operations.
      $operation = new AdGroupCriterionOperation();
      $operation->operand = $adGroupCriterion;
      $operation->operator = 'SET';

      $operations = array($operation);

      // Update ad group criteria.
      $result = $adGroupCriteriaService->mutate($operations);

I am using 

- aw_api_php_lib_2.0.1
- php 5.2.1

Here is the SOAP request and Response,

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v200909"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SOAP-ENV:Header>
    <ns1:RequestHeader xsi:type="ns1:RequestHeader">
      <ns1:applicationToken>xxxxxx</ns1:applicationToken>
      <ns1:authToken>xxxx</ns1:authToken>
      <ns1:clientEmail>xxxxx</ns1:clientEmail>
      <ns1:developerToken>xxxxx</ns1:developerToken>
      <ns1:userAgent>AwApi-PHP-2.0.1-perfectstormmedia</ns1:userAgent>
    </ns1:RequestHeader>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <ns1:mutate>
      <ns1:operations
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v200909"
xsi:type="ns1:AdGroupCriterionOperation">
        <ns1:operator>SET</ns1:operator>
        <ns1:operand
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v200909"
xsi:type="ns1:BiddableAdGroupCriterion">
          <ns1:adGroupId>996759724</ns1:adGroupId>
          <ns1:criterion
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v200909"
xsi:type="ns1:Criterion">
            <ns1:id>11286263724</ns1:id>
          </ns1:criterion>
          <ns1:bids
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v200909"
xsi:type="ns1:ManualCPCAdGroupCriterionBids">
            <ns1:maxCpc
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v200909"
xsi:type="ns1:Bid">
              <ns1:amount
xmlns:ns1="https://adwords.google.com/api/adwords/cm/v200909"
xsi:type="ns1:Money">
                <ns1:microAmount>16079999</ns1:microAmount>
              </ns1:amount>
            </ns1:maxCpc>
          </ns1:bids>
        </ns1:operand>
      </ns1:operations>
    </ns1:mutate>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

HTTP/1.1 500 Internal Server Error
Content-Type: text/xml; charset=UTF-8
Content-Encoding: gzip
Transfer-Encoding: chunked
Date: Tue, 06 Apr 2010 12:08:50 GMT
Expires: Tue, 06 Apr 2010 12:08:50 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <ResponseHeader xmlns="https://adwords.google.com/api/adwords/cm/v200909">
      <requestId>0dc304d089fcb65a27814ada84ee7cca</requestId>
      <operations>1</operations>
      <responseTime>575</responseTime>
      <units>3</units>
    </ResponseHeader>
  </soap:Header>
  <soap:Body>
    <soap:Fault>
      <faultcode>soap:Server</faultcode>
      <faultstring>[BiddingError.BID_TOO_MANY_FRACTIONAL_DIGITS @
operations[0].operand.bids.maxCpc.amount.microAmount]</faultstring>
      <detail>
        <ApiExceptionFault
xmlns="https://adwords.google.com/api/adwords/cm/v200909">
          <message>[BiddingError.BID_TOO_MANY_FRACTIONAL_DIGITS @
operations[0].operand.bids.maxCpc.amount.microAmount]</message>
          <ApplicationException.Type>ApiException</ApplicationException.Type>
          <errors xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="BiddingError">

<fieldPath>operations[0].operand.bids.maxCpc.amount.microAmount</fieldPath>
            <trigger/>
            <ApiError.Type>BiddingError</ApiError.Type>
            <reason>BID_TOO_MANY_FRACTIONAL_DIGITS</reason>
          </errors>
        </ApiExceptionFault>
      </detail>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

Original issue reported on code.google.com by tomnabie...@perfectstormmedia.com on 6 Apr 2010 at 12:36

GoogleCodeExporter commented 8 years ago
I've seen this problem before, and a quick solution is to cast the value to a 
float 
before passing it into the Money constructor.  From what I've seen the number 
only 
gets corrupted once inside the SoapClient class, but I'll look into a more 
holistic 
solution to prevent this in the future.

Original comment by api.ekol...@gmail.com on 6 Apr 2010 at 2:23

GoogleCodeExporter commented 8 years ago
Thanks for the quick reply.

I have tried the suggested quick solution (float type casting), but that also 
not
working.

Here is my updated code after applying float,

 // Create bids.
      $bids = new ManualCPCAdGroupCriterionBids();

      $newMaxCpc = $newMaxCpc * 1000000;
      $newMaxCpc = (float) $newMaxCpc;

      $bids->maxCpc = new Bid(new Money($newMaxCpc));
      $adGroupCriterion->bids = $bids;

I have also applied (float) in the main 'AdGroupCriterionService.php' file, but 
that
didn't changed anything in the SOAP request.

...

public function __construct($microAmount = NULL, $ComparableValueType = NULL) {
    if(get_parent_class('Money')) parent::__construct();
    $this->microAmount = (float) $microAmount;
    $this->ComparableValueType = $ComparableValueType;
  }

...

I have tested this on Windows as well as on Linux machine.

Please let me know if you need any further details.

Original comment by tomnabie...@perfectstormmedia.com on 6 Apr 2010 at 3:04

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
This is unusual but, when I am passing MaxCPC as '16.09', its working. So, 
wondering
why the '16.08' causing the issue.

Original comment by tomnabie...@perfectstormmedia.com on 6 Apr 2010 at 3:11

GoogleCodeExporter commented 8 years ago
My understanding is that this has to do with the precision of floats in PHP:

  http://php.net/manual/en/language.types.float.php

I'm not able to replicate this issue on my machine, but another user saw 
success 
casting to floats:

  http://groups.google.com/group/adwords-
api/browse_thread/thread/f8e1a08b10d20079/8c32de9c3ef6e084?
show_docid=8c32de9c3ef6e084

Can you verify if the number is incorrect before being passed into SoapClient 
or if 
it is SoapClient that is converting it incorrectly?

Original comment by api.ekol...@gmail.com on 6 Apr 2010 at 5:35

GoogleCodeExporter commented 8 years ago
I have noted that the MaxCPC value '16080000' remain same till the
parent::__soapCall() statement (AdsSoapClient.php), after the soap call the soap
request showing it as '16079999'. This means the SoapClient converting it 
incorrectly.

The data type for microAmount is Long and I think the SoapClient not converting 
float
value correctly in this case. I have found similar issue posted by someone here,

http://bugs.php.net/bug.php?id=48717&thanks=6

Here is the output of var_dump($arguments); statement, taken just above the
parent::__soapCall().

array(1) {
  [0]=>
  object(AdGroupCriterionServiceMutate)#10 (1) {
    ["operations"]=>
    array(1) {
      [0]=>
      object(AdGroupCriterionOperation)#9 (5) {
        ["operand"]=>
        object(BiddableAdGroupCriterion)#4 (12) {
          ["userStatus"]=>
          NULL
          ["systemServingStatus"]=>
          NULL
          ["approvalStatus"]=>
          NULL
          ["destinationUrl"]=>
          NULL
          ["bids"]=>
          object(ManualCPCAdGroupCriterionBids)#6 (5) {
            ["maxCpc"]=>
            object(Bid)#7 (1) {
              ["amount"]=>
              object(Money)#8 (3) {
                ["microAmount"]=>
                float(16080000)
                ["ComparableValueType"]=>
                NULL
                ["_parameterMap:private"]=>
                array(1) {
                  ["ComparableValue.Type"]=>
                  string(19) "ComparableValueType"
                }
              }
            }
            ["bidSource"]=>
            NULL
            ["positionPreferenceBids"]=>
            NULL
            ["AdGroupCriterionBidsType"]=>
            NULL
            ["_parameterMap:private"]=>
            array(1) {
              ["AdGroupCriterionBids.Type"]=>
              string(24) "AdGroupCriterionBidsType"
            }
          }
          ["firstPageCpc"]=>
          NULL
          ["qualityInfo"]=>
          NULL
          ["stats"]=>
          NULL
          ["adGroupId"]=>
          float(996459724)
          ["criterion"]=>
          object(Criterion)#5 (3) {
            ["id"]=>
            float(11281263724)
            ["CriterionType"]=>
            NULL
            ["_parameterMap:private"]=>
            array(1) {
              ["Criterion.Type"]=>
              string(13) "CriterionType"
            }
          }
          ["AdGroupCriterionType"]=>
          NULL
          ["_parameterMap:private"]=>
          array(1) {
            ["AdGroupCriterion.Type"]=>
            string(20) "AdGroupCriterionType"
          }
        }
        ["exemptionRequests"]=>
        NULL
        ["operator"]=>
        string(3) "SET"
        ["OperationType"]=>
        NULL
        ["_parameterMap:private"]=>
        array(1) {
          ["Operation.Type"]=>
          string(13) "OperationType"
        }
      }
    }
  }
}

Original comment by tomnabie...@perfectstormmedia.com on 7 Apr 2010 at 7:25

GoogleCodeExporter commented 8 years ago
On my machine I'm actually seeing the value being output incorrect before it 
gets 
passed into the Money constructor.  I've seen some success applying the round() 
function to the value before passing it into the constructor though.  Can you 
try this 
and let me know if it helps?

Original comment by api.ekol...@gmail.com on 7 Apr 2010 at 1:31

GoogleCodeExporter commented 8 years ago
I have tried String type casting on the MaxCPC value, before passing it into the
Money constructor and it works.

$newMaxCpc1 = (string) $newMaxCpc;

The updated code,

// Create bids.
      $bids = new ManualCPCAdGroupCriterionBids();

      $newMaxCpc = ($newMaxCpc * 1000000);
      $newMaxCpc1 = (string) $newMaxCpc;

      $bids->maxCpc = new Bid(new Money($newMaxCpc1));
      $adGroupCriterion->bids = $bids;

I don't know how this worked, may be you can comment on this.

Thanks for your support.

Original comment by tomnabie...@perfectstormmedia.com on 7 Apr 2010 at 2:53

GoogleCodeExporter commented 8 years ago
There are know issues with using strings for large numerical values (see issue 
#5).  
Can you try using round instead and let me know if that works?

Original comment by api.ekol...@gmail.com on 7 Apr 2010 at 3:00

GoogleCodeExporter commented 8 years ago

Original comment by api.ekol...@gmail.com on 8 Apr 2010 at 4:06

GoogleCodeExporter commented 8 years ago

Original comment by api.ekol...@gmail.com on 8 Apr 2010 at 4:06

GoogleCodeExporter commented 8 years ago
Yes, I tried it with using round() function and it works as well. Here is the 
updated
code,

// Create bids.
      $bids = new ManualCPCAdGroupCriterionBids();

      $newMaxCpc = ($newMaxCpc * 1000000);
      $newMaxCpc1 = round($newMaxCpc);

      $bids->maxCpc = new Bid(new Money($newMaxCpc1));
      $adGroupCriterion->bids = $bids;

You can see that, I haven't applied any other options in the round() function. 
The
round function returns result as a float value, but I am wondering what it makes
difference for MaxCPC value so that it works with round() and String type 
casting and
not with Flaot type casting?

It helps if you throw some light on this issue.

Thanks,

: Janak Prajapati

Original comment by tomnabie...@perfectstormmedia.com on 9 Apr 2010 at 5:20

GoogleCodeExporter commented 8 years ago
The problem appears to be due to precision issues in PHP multiplication.  Using 
the round() function removed the extra digits and allowed for the correct value.

Original comment by api.ekol...@gmail.com on 30 Jun 2010 at 6:29