Hi all,

First of all, please note that for some reason, neither 'Quote' nor the 
'Code' functionality appears to be working. Also, it seems that no 
formatting works whatsoever, for some reason, so sorry about the mess.

I'm sure we are missing something extremely simple, but it is now eating up 
a lot of time, and was wondering if anyone could point us in the right 
direction.

What we would like to achieve is replacing the FinalURLs of a number of 
ExpandedTextAds using BatchJobService and SET.

What we did was take a previously functional code which uses the operator 
ADD and modify that to use SET. However, when doing so, we get the 
following error:

            [0] => Google\AdsApi\AdWords\v201710\cm\RequiredError Object
                (
                    [reason:protected] => REQUIRED
                    [fieldPath:protected] => operations[0].operand.id
                    [fieldPathElements:protected] => Array
                        (
                            [0] => 
Google\AdsApi\AdWords\v201710\cm\FieldPathElement Object
                                (
                                    [field:protected] => operations
                                    [index:protected] => 0
                                )

                            [1] => 
Google\AdsApi\AdWords\v201710\cm\FieldPathElement Object
                                (
                                    [field:protected] => operand
                                    [index:protected] => 
                                )

                            [2] => 
Google\AdsApi\AdWords\v201710\cm\FieldPathElement Object
                                (
                                    [field:protected] => id
                                    [index:protected] => 
                                )

                        )

                    [trigger:protected] => 
                    [errorString:protected] => RequiredError.REQUIRED
                    [ApiErrorType:protected] => RequiredError


Suffice to say, we are missing an id somewhere. But how and where are we 
missing it? There are no examples to help us down the path. Our current 
code is:

function updateTextAdsCriterionOperations($expandText) {
    $ExpandedTextAdsOperations = [];
    
    foreach ($expandText as $adText) {
        // Create an expanded text ad.
        $expandedTextAd = new ExpandedTextAd();
        $expandedTextAd->setId( $adText[4] );
        $expandedTextAd->setHeadlinePart1( $adText[5] );
        $expandedTextAd->setHeadlinePart2( $adText[6] );
        $expandedTextAd->setDescription( $adText[7] );
        $expandedTextAd->setFinalUrls([ $adText[10] ]);
        $expandedTextAd->setPath1( $adText[8] );
        $expandedTextAd->setPath2( $adText[9] );
//        $expandedTextAd->setStatus( ExpandedTextAd::PAUSED );
        // Create ad group ad.
        $adGroupAd = new AdGroupAd();
        $adGroupAd->setAdGroupId( $adText[2] );
        $adGroupAd->setAd( $expandedTextAd );
        // Optional: Set additional settings.
        $adGroupAd->setStatus( AdGroupAdStatus::PAUSED );
        // Create ad group ad operation and add it to the list.
        $operation = new AdGroupAdOperation();
        $operation->setOperand( $adGroupAd );
        $operation->setOperator( Operator::SET );
        $ExpandedTextAdsOperations[] = $operation;
//        file_put_contents("batchjob.txt", print_r($operation, true), 
FILE_APPEND);
    }
    
    return $ExpandedTextAdsOperations;
}

function UploadSettings(AdWordsServices $adWordsServices, AdWordsSession 
$session, $expAdTextAds) {
     try {
        $batchJobService = $adWordsServices->get($session, 
BatchJobService::class);
        // Create a BatchJob.
        $addOp = new BatchJobOperation();
        $addOp->setOperator(Operator::SET);
        $addOp->setOperand(new BatchJob());
        $result = $batchJobService->mutate([$addOp]);
        $batchJob = $result->getValue()[0];
        // Get the upload URL from the new job.
        $uploadUrl = $batchJob->getUploadUrl()->getUrl();
        printf("Created BatchJob with ID %d, status '%s' and upload URL 
'%s'.<br>",
            $batchJob->getId(), $batchJob->getStatus(), $uploadUrl);
        // Use BatchJobs to upload all operations.
        $batchJobs = new BatchJobs($session);
        
        // Generate and upload the first set of operations.
        $adGroupCriterionOperations = 
updateTextAdsCriterionOperations($expAdTextAds);
        $batchJobUploadStatus = 
$batchJobs->uploadIncrementalBatchJobOperations(
            $adGroupCriterionOperations,
            new BatchJobUploadStatus($uploadUrl, $session)
        );
        printf("Uploaded %d operations for batch job with ID %d.<br>",
            count($adGroupCriterionOperations), $batchJob->getId());
        
        $batchJobs->closeIncrementalUpload($batchJobUploadStatus);
        // Poll for completion of the batch job using an exponential back 
off. 
    } catch (Exception $e) {
        echo "<pre>";
        print_r($e);
        echo "</pre>";
    }
    $pollAttempts = 0;
    $isPending = true;
    $wasCancelRequested = false;
    $selector = new Selector();
    $selector->setFields(
        ['Id', 'Status', 'DownloadUrl', 'ProcessingErrors', 
'ProgressStats']);
    $selector->setPredicates([
        new Predicate('Id', PredicateOperator::EQUALS, [$batchJob->getId()])
    ]);
    do {
        $sleepSeconds = POLL_FREQUENCY_SECONDS * pow(2, $pollAttempts);
        printf("Sleeping %d seconds...<br>", $sleepSeconds);
        sleep($sleepSeconds);
        $batchJob = $batchJobService->get($selector)->getEntries()[0];
        printf("Batch job ID %d has status '%s'.<br>", $batchJob->getId(),
            $batchJob->getStatus());
        $pollAttempts++;
        if ($batchJob->getStatus() !== BatchJobStatus::ACTIVE &&
            $batchJob->getStatus() !== BatchJobStatus::AWAITING_FILE &&
            $batchJob->getStatus() !== BatchJobStatus::CANCELING) {
                $isPending = false;
            }
            // Optional: Cancel the job if it has not completed after 
polling
            // MAX_POLL_ATTEMPTS times.
            if ($isPending && !$wasCancelRequested
                && $pollAttempts === MAX_POLL_ATTEMPTS) {
                    $batchJob->setStatus(BatchJobStatus::CANCELING);
                    $batchJobSetOperation = new BatchJobOperation();
                    $batchJobSetOperation->setOperand($batchJob);
                    $batchJobSetOperation->setOperator(Operator::SET);
                    // Only request cancellation once per job.
                    $wasCancelRequested = true;
                    try {
                        $batchJob =
                        
$batchJobService->mutate([$batchJobSetOperation])->getValue()[0];
                        printf("Requested cancellation of batch job with ID 
%d.<br>",
                            $batchJob->getId());
                        // Reset the poll attempt counter to wait for 
cancellation.
                        $pollAttempts = 0;
                    } catch (ApiException $e) {
                        $errors = $e->getErrors();
                        if ($errors !== null
                            && count($errors) > 0
                            && $errors[0] instanceof BatchJobError) {
                                $batchJobError = $errors[0];
                                if ($batchJobError->getReason()
                                    === 
BatchJobErrorReason::INVALID_STATE_CHANGE) {
                                        printf(
                                            "Attempt to cancel batch job 
with ID %d was rejected because"
                                            . " the job already completed 
or was canceled.<br>",
                                            $batchJob->getId()
                                            );
                                        continue;
                                    }
                            }
                            throw $e;
                    } finally {
                        // Reset the poll attempt counter to wait for 
cancellation.
                        $pollAttempts = 0;
                    }
                }
    } while ($isPending && $pollAttempts <= MAX_POLL_ATTEMPTS);
    if ($isPending) {
        throw new UnexpectedValueException(
            sprintf('Job is still pending state after polling %d times.',
                MAX_POLL_ATTEMPTS));
    }
    if ($batchJob->getProcessingErrors() !== null) {
        $i = 0;
        foreach ($batchJob->getProcessingErrors() as $processingError) {
            printf(
                " Processing error [%d]: errorType=%s, trigger=%s, 
errorString=%s,"
                . " fieldPath=%s, reason=%s<br>",
                $i++,
                $processingError->getApiErrorType(),
                $processingError->getTrigger(),
                $processingError->getErrorString(),
                $processingError->getFieldPath(),
                $processingError->getReason()
                );
        }
    } else {
        printf("No processing errors found.<br>");
    }
    if ($batchJob->getDownloadUrl() !== null
        && $batchJob->getDownloadUrl()->getUrl() !== null) {
            $mutateResults = $batchJobs->downloadBatchJobResults(
                $batchJob->getDownloadUrl()->getUrl());
            printf("Downloaded results from %s:<br>",
                $batchJob->getDownloadUrl()->getUrl());
            if (count($mutateResults) === 0) {
                printf("  No results available.<br>");
            } else {
                foreach ($mutateResults as $mutateResult) {
                    $outcome = $mutateResult->getErrorList() === null ? 
'SUCCESS' : 'FAILURE';
                    printf("  Operation [%d] - %s<br>", 
$mutateResult->getIndex(),
                        $outcome);
                    if ( $outcome == "FAILURE" ){
                        print_r( $mutateResult->getErrorList() );
                    }
                }
            }
        } else {
            printf("No results available for download.<br>");
        }
}

So we have "UploadSettings" called and we get the error somewhere right 
after or at " $result = $batchJobService->mutate([$addOp]);". The thing is, 
the code never even seems to get around to adding the expanded text ad 
parameters. Can anyone help out with what we're exactly missing?

-- 
-- 
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~
Also find us on our blog and Google+:
https://googleadsdeveloper.blogspot.com/
https://plus.google.com/+GoogleAdsDevelopers/posts
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~

You received this message because you are subscribed to the Google
Groups "AdWords API Forum" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/adwords-api?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"AdWords API Forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/adwords-api.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/adwords-api/0e88f92b-adbc-486c-b6cc-f98ac35e3b5e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
  • BatchJob... Prototype.co
    • Re:... 'Sreelakshmi Sasidharan (AdWords API Team)' via AdWords API Forum
      • ... Prototype.co
        • ... 'Sreelakshmi Sasidharan (AdWords API Team)' via AdWords API Forum
          • ... Prototype.co
            • ... 'Sreelakshmi Sasidharan (AdWords API Team)' via AdWords API Forum

Reply via email to