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.