Expression Rule User List Error

239 views
Skip to first unread message

danny+...@pdffiller.com

unread,
Jun 22, 2018, 2:37:08 AM6/22/18
to AdWords API and Google Ads API Forum
Hi! I am trying to create custom audience, but have UserListError.CONCRETE_TYPE_REQUIRE Error.

public function addCustomIntentList(array $data)
{
    $expressionUserList = new ExpressionRuleUserList();

    $expressionUserList->setName('Test item');
    $expressionUserList->setDescription(
        'Test description'
    );

    $expressionUserList->setPrepopulationStatus(
        RuleBasedUserListPrepopulationStatus::REQUESTED
    );

    $expressionUserList->setRule(self::createUserListRule($data));

    $operation = new \Google\AdsApi\AdWords\v201710\rm\UserListOperation();
    $operation->setOperand($expressionUserList);
    $operation->setOperator(\Google\AdsApi\AdWords\v201710\cm\Operator::ADD);

    return $this->mutateOperations([$operation])[0];
}

/**
 * Create a user list rule composed of two rule item groups.
 * @param array $data
 *
 * @return Rule the created rule
 */
private static function createUserListRule(array $data)
{
    $ruleItems = [];

    foreach ($data as $ruleItem) {
        $stringRuleItem = new StringRuleItem();
        $stringKey = new StringKey();
        $stringKey->setName($ruleItem);
        $stringRuleItem->setKey($stringKey);
        $stringRuleItem->setOp(StringRuleItemStringOperator::EQUALS);
        $stringRuleItem->setValue($ruleItem);

        $newRuleItem = new RuleItem();
        $newRuleItem->setStringRuleItem($stringRuleItem);

        $ruleItems[] = $newRuleItem;
    }

    $multipleItemGroup = new RuleItemGroup();
    $multipleItemGroup->setItems(
        $ruleItems
    );

    $rule = new Rule();
    $rule->setGroups(
        [$multipleItemGroup]
    );

    $rule->setRuleType(UserListRuleTypeEnumsEnum::DNF);

    return $rule;
}


addCustomIntentList(array $data - array of strings(domains), which I need to save via API programmatically like keywords in UI version:

Thank you for help!

Peter Oliquino (AdWords API Team)

unread,
Jun 22, 2018, 4:15:44 AM6/22/18
to AdWords API and Google Ads API Forum
Hi Danny,

Could you review your SOAP request if the below element is being included?

<operand xmlns:ns8="https://adwords.google.com/api/adwords/rm/v201806xsi:type="ns8:ExpressionRuleUserList">

If the above operand code is not present in your request, could you send to me the complete SOAP request and response logs so I can further investigate?

You may reply to me via the Reply privately to author option.

Thanks and regards,
Peter
AdWords API Team
Message has been deleted

danny+...@pdffiller.com

unread,
Jun 22, 2018, 7:39:34 AM6/22/18
to AdWords API and Google Ads API Forum
I found error, but it was not correct audience type for me. I need custom intent, not "website visitors". I found it in v201806
How can I create correct Intent to use CriterionCustomIntent as next:

public function createCustomIntentCriterion(array $data)
{
$operations = [];

foreach ($data as $item) {
if (!isset($item['AdGroupId'])) {
throw new AdWordsClientException('AdGroupId is not set');
}
if (!isset($item['CustomIntentId'])) {
throw new AdWordsClientException('CustomIntentId is not set');
}

$userListCriterion = new CriterionCustomIntent();
$userListCriterion->setCustomIntentId($item['CustomIntentId']);

$adGroupCriterion = new BiddableAdGroupCriterion();
$adGroupCriterion->setAdGroupId($item['AdGroupId']);
$adGroupCriterion->setCriterion($userListCriterion);

$operations[] = new AdGroupCriterionOperation(Operator::ADD, null, $adGroupCriterion);
}

return $this->mutateOperations($operations);
}

I did not find example how create intent, which will return data with CustomIntentId ?

Peter Oliquino (AdWords API Team)

unread,
Jun 25, 2018, 1:24:53 AM6/25/18
to AdWords API and Google Ads API Forum
Hi Danny,

Could you first confirm if you no longer have any issues with the ExpressionRuleUserList ADD request, and that what originally intended was to create a CriterionCustomIntent as a BiddableAdGroupCriterion

danny+...@pdffiller.com

unread,
Jun 25, 2018, 3:41:13 AM6/25/18
to AdWords API and Google Ads API Forum
Yes. Error with ExpressionRuleUserList was that in including files part I had different library versions for classes. It produced incorrect SOAP request. But after execution code I understood that it was not what I needed. I need a CriterionCustomIntent to create audience for users, who visited domains, which I need add to intent list as keywords. 
Type of that audience in UI is 'Custom intent audience'.

Unfortunately I found no examples how to use CriterionCustomIntent.

Nadine Sundquist (AdWords API Team)

unread,
Jun 25, 2018, 5:43:23 PM6/25/18
to AdWords API and Google Ads API Forum
Hello Danny,

There was a new service introduced in v201806 called CustomAffinityService. If you already have custom audiences in your account, then you'll see them there. You can use the ID from those. You can also create audiences using the CustomAffinityService. In that service, you'll get back two types of audiences, CUSTOM_INTENT and CUSTOM_AFFINITY. You'll want to use the CUSTOM_INTENT one for a CriterionCustomIntent

Cheers,
Nadine, AdWords API Team

danny+...@pdffiller.com

unread,
Jun 26, 2018, 9:23:51 AM6/26/18
to AdWords API and Google Ads API Forum
Hi Nadine!

Thank you, I successfully created Custom Intent due to your manual, but now have trouble how to link Intent to AdGroup if I have IntentID and AdGroup ID?

My way with error:

$operations = [];

foreach ($data as $item) {
if (!isset($item['AdGroupId'])) {
throw new AdWordsClientException('AdGroupId is not set');
}
if (!isset($item['CustomIntentId'])) {
throw new AdWordsClientException('CustomIntentId is not set');
}

$userListCriterion = new CriterionCustomIntent();
$userListCriterion->setCustomIntentId($item['CustomIntentId']);

$adGroupCriterion = new BiddableAdGroupCriterion();
$adGroupCriterion->setAdGroupId($item['AdGroupId']);
$adGroupCriterion->setCriterion($userListCriterion);

    $operations[] = new CustomAffinityOperation(Operator::ADD, null, $adGroupCriterion);
}

return $this->mutateOperations($operations);

Produces error:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><ns2:ResponseHeader xmlns:ns2="https://adwords.google.com/api/adwords/rm/v201806" xmlns="https://adwords.google.com/api/adwords/cm/v201806"><requestId>00056f8b200ebf800a81ed01ae020b82</requestId><serviceName>CustomAffinityService</serviceName><methodName>mutate</methodName><operations>1</operations><responseTime>586</responseTime></ns2:ResponseHeader></soap:Header><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>[RequiredError.REQUIRED @ operations[0].operand.name]</faultstring><detail><ns2:ApiExceptionFault xmlns="https://adwords.google.com/api/adwords/cm/v201806" xmlns:ns2="https://adwords.google.com/api/adwords/rm/v201806"><message>[RequiredError.REQUIRED @ operations[0].operand.name]</message><ApplicationException.Type>ApiException</ApplicationException.Type><errors xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="RequiredError"><fieldPath>operations[0].operand.name</fieldPath><fieldPathElements><field>operations</field><index>0</index></fieldPathElements><fieldPathElements><field>operand</field></fieldPathElements><fieldPathElements><field>name</field></fieldPathElements><trigger></trigger><errorString>RequiredError.REQUIRED</errorString><ApiError.Type>RequiredError</ApiError.Type><reason>REQUIRED</reason></errors></ns2:ApiExceptionFault></detail></soap:Fault></soap:Body></soap:Envelope>


But sent SOAP looks little bit strange with no data except operation type:

<?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/v201806" xmlns:ns2="https://adwords.google.com/api/adwords/rm/v201806"><SOAP-ENV:Header><ns2:RequestHeader><ns1:clientCustomerId>***</ns1:clientCustomerId><ns1:developerToken>REDACTED</ns1:developerToken><ns1:userAgent>unknown (AwApi-PHP, googleads-php-lib/35.2.0, PHP/5.6.31-1~ubuntu14.04.1+deb.sury.org+1)</ns1:userAgent><ns1:validateOnly>false</ns1:validateOnly><ns1:partialFailure>false</ns1:partialFailure></ns2:RequestHeader></SOAP-ENV:Header><SOAP-ENV:Body><ns2:mutate><ns2:operations><ns1:operator>ADD</ns1:operator><ns2:operand/></ns2:operations></ns2:mutate></SOAP-ENV:Body></SOAP-ENV:Envelope>

Nadine Sundquist (AdWords API Team)

unread,
Jun 26, 2018, 11:42:56 AM6/26/18
to AdWords API and Google Ads API Forum
Hello Danny,

That first error that you have with the REQUIRED is actually coming from CustomAffinityService. This is when you are creating your audience. It's saying that a name is required. So, it looks like that call to create your custom affinity audience failed due to that. Please make sure to specify a name.

The reason the second may be empty is because it looks like your first call to make the audience failed. Could you double-check to make sure that your first call really is successful and then try the second one again?

Thanks,
Nadine, AdWords API Team

danny+...@pdffiller.com

unread,
Jun 26, 2018, 5:22:58 PM6/26/18
to AdWords API and Google Ads API Forum
I checked creation of intent, and got successful response:

Array

(

    [0] => Array

        (

            [Id] => 2610756

            [Status] => ENABLED

            [Name] => Test Custom Audience 3

            [Type] => CUSTOM_INTENT

            [Description] => Test Custom Audience 3 created at 08:57:48 26:06:2018

            [Tokens] => Array

                (

                    [0] => Array

                        (

                            [CustomAffinityId] => 2610756

                            [CustomAffinityTokenId] => 22592718

                            [TokenType] => URL

                            [Parameter] => rere.com

                        )


                )


        )


)


I tried use CustomAffinityService with next values: 

[['AdGroupId' => ***, 'CustomIntentId' => 2610756]];


Where CustomIntentId is id from first query response.

$operations
looks like this after I set all values im method which I attached in prev post:

Array

(

    [0] => Google\AdsApi\AdWords\v201806\cm\AdGroupCriterionOperation Object

        (

            [operand:protected] => Google\AdsApi\AdWords\v201806\cm\AdGroupCriterion Object

                (

                    [adGroupId:protected] => ***

                    [criterionUse:protected] => 

                    [criterion:protected] => Google\AdsApi\AdWords\v201806\cm\CriterionCustomIntent Object

                        (

                            [customIntentId:protected] => 2610756

                            [id:protected] => 

                            [type:protected] => 

                            [CriterionType:protected] => CUSTOM_INTENT

                            [parameterMap:Google\AdsApi\AdWords\v201806\cm\Criterion:private] => Array

                                (

                                    [Criterion.Type] => CriterionType

                                )


                        )


                    [labels:protected] => 

                    [forwardCompatibilityMap:protected] => 

                    [baseCampaignId:protected] => 

                    [baseAdGroupId:protected] => 

                    [AdGroupCriterionType:protected] => 

                    [parameterMap:Google\AdsApi\AdWords\v201806\cm\AdGroupCriterion:private] => Array

                        (

                            [AdGroupCriterion.Type] => AdGroupCriterionType

                        )


                )


            [exemptionRequests:protected] => 

            [operator:protected] => ADD

            [OperationType:protected] => 

            [parameterMap:Google\AdsApi\AdWords\v201806\cm\Operation:private] => Array

                (

                    [Operation.Type] => OperationType

                )


        )


)


Thanks, Danny.

danny+...@pdffiller.com

unread,
Jun 26, 2018, 5:28:01 PM6/26/18
to AdWords API and Google Ads API Forum
I also added next value:

$userListCriterion->setCriterionType(CriterionType::CUSTOM_INTENT);

so now I have:

$userListCriterion = new CriterionCustomIntent();
$userListCriterion->setCustomIntentId($item['CustomIntentId']);
    $userListCriterion->setCriterionType(CriterionType::CUSTOM_INTENT);

And switched BiddableAdGroupCriterion to AdGroupCriterion()

But nothing changed.

Danny.

Nadine Sundquist (AdWords API Team)

unread,
Jun 28, 2018, 12:33:45 PM6/28/18
to AdWords API and Google Ads API Forum
Hi Danny,

My apologies for the delay. At first it looked like in your post that you had solved the issue. I just re-read it, and I can see that you're still trying to get this figured out. So, I searched through our logs for your request and your response. I found the reason why you're having a failure by finding your request and response in our logs.

If you look at your response, you'll see that you're getting back an error that says OperationAccessDenied.OPERATION_NOT_PERMITTED_FOR_CAMPAIGN_TYPE @ operations[0].operand.criterion; trigger:'SEARCH. You can't use this type of criterion for search campaigns. It's only meant for display campaigns. You can read more about the types of campaigns where you can use audiences in the AdWords Help Center's article on audience targeting. Once you try this same code on a display campaign, then this should work.

Best,
Nadine, AdWords API Team

danny+...@pdffiller.com

unread,
Jul 3, 2018, 8:43:24 AM7/3/18
to AdWords API and Google Ads API Forum
Hi Nadine!

I tried code for:

[AdGroupId] => 25768077653
[CustomIntentId] => 2608877

This AdGroup has display type, it's campaign also, I checked. But I am still having error "[RequiredError.REQUIRED @ operations[0].operand.name".
Something is wrong. Maybe I set not all necessary parameters? Check please via your logs.

Sincerely, Danny.

Nadine Sundquist (AdWords API Team)

unread,
Jul 3, 2018, 2:46:58 PM7/3/18
to AdWords API and Google Ads API Forum
Hello Danny,

Could you please send me the requestId that comes back with your request? You should see it in your SOAP XML logs, and it would look similar to the one in this example. It's much easier to find the request on our log servers when we have that requestId. If you're using the PHP client library, there are instructions here on how to turn on SOAP logging. I can't currently find the request that you've mentioned on our logs because we get so many update to ad group criterion. 

Also, I want to make a quick note that in the USA we are about to have national holidays, so you may not hear from me for several days. I'll follow up as soon as we come back from the holidays.

Thanks,
Nadine, AdWords API Team

danny+...@pdffiller.com

unread,
Jul 4, 2018, 3:59:16 AM7/4/18
to AdWords API and Google Ads API Forum
Hi Nadine, 

I have enabled logs already, so here is requestId - 00057017946dc9980a0dc447e2010d3a
Sure, I will wait for your answer. Have a nice holidays)

Danny.

Nadine Sundquist (AdWords API Team)

unread,
Jul 9, 2018, 9:22:23 AM7/9/18
to AdWords API and Google Ads API Forum
Hi Danny,

I'm back from the holidays! Woohoo! Thank you for letting me get the chance to take a break, and thank you for sending me the request ID. That makes it soooooooo much easier for me.  

So, here's your request and response that I've found on our servers for that request ID. You should also be able to see the same thing in your SOAP logs if you turn on the DEBUG level. I've removed any sensitive information from the request and response.

Request;
<ns2:mutate><ns2:operations><ns1:operator>ADD</ns1:operator><ns2:operand/></ns2:operations></ns2:mutate>

Response:
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""><soap:Header><ns2:ResponseHeader xmlns:ns2=""https://adwords.google.com/api/adwords/rm/v201806"" xmlns=""https://adwords.google.com/api/adwords/cm/v201806""><requestId>00057017946dc9980a0dc447e2010d3a</requestId><serviceName>CustomAffinityService</serviceName><methodName>mutate</methodName><operations>1</operations><responseTime>439</responseTime></ns2:ResponseHeader></soap:Header><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>[RequiredError.REQUIRED @ operations[0].operand.name]</faultstring><detail><ns2:ApiExceptionFault xmlns=""https://adwords.google.com/api/adwords/cm/v201806"" xmlns:ns2=""https://adwords.google.com/api/adwords/rm/v201806""><message>[RequiredError.REQUIRED @ operations[0].operand.name]</message><ApplicationException.Type>ApiException</ApplicationException.Type><errors xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""RequiredError""><fieldPath>operations[0].operand.name</fieldPath><fieldPathElements><field>operations</field><index>0</index></fieldPathElements><fieldPathElements><field>operand</field></fieldPathElements><fieldPathElements><field>name</field></fieldPathElements><trigger></trigger><errorString>RequiredError.REQUIRED</errorString><ApiError.Type>RequiredError</ApiError.Type><reason>REQUIRED</reason></errors></ns2:ApiExceptionFault></detail></soap:Fault></soap:Body></soap:Envelope>

The problem is that for that particular error, CustomAffinityService is being called with an ADD operation, but no name is being sent in on the ADD. I've highlighted where in the error it's trying to tell you this. So, an error is coming back saying that it is required. 

I hope that helps you solve the mysterious issue you're having. You may want to turn on DEBUG in your SOAP logging until you have everything working. That way you can see everything I see. After that, you can turn it all off.

Cheers,
Nadine, AdWords API Team

danny+...@pdffiller.com

unread,
Jul 10, 2018, 8:15:55 AM7/10/18
to AdWords API and Google Ads API Forum
Hi Nadine!

Glad to see you again!
But I can not see how set name for ADD operation.

At first I created CriterionCustomAffinity or CriterionCustomIntent (tried both)
Than set custom affinity/intent id (2608877). also added criterion type - CUSTOM_INTENT or CUSTOM_AFFINITY (but I created affinity with type CustomAffinityType::CUSTOM_INTENT)

After I created AdGroupCriterion.
Set adGroupId (25768077653), and set criterion, which created before. 

After created AdGroupCriterionOperation with operator ADD, operation type null and AdGroupCriterion as operand. but I can not set name for AdGroupCriterion - there is no such method. On which step I am wrong? May be I am using wrong adGroup operation or criterion?

Sincerely, Danny.

Nadine Sundquist (AdWords API Team)

unread,
Jul 10, 2018, 12:39:41 PM7/10/18
to AdWords API and Google Ads API Forum
Hello Danny,

I think there may be a bit confusion here in what I explained, so let me take a set back here to explain. Your error is not happening in the second step that you're explaining here. Your error is happening even before you create the criterion. When you first create your CustomAffinity object, you need to set the name. In the CustomAffinity object when you do an ADD, you need to set the name. That requestId you sent me with that error is saying that the error is happening that early in the process, so please take a look at your earlier code and make sure that you are setting the name. 

Thanks,
Nadine, AdWords API Team

danny+...@pdffiller.com

unread,
Jul 11, 2018, 6:11:13 AM7/11/18
to AdWords API and Google Ads API Forum
Hi Nadine!

As I explained before, I am creating custom intent in one part of code, and created it successful. I am getting response with all info about custom intent (id, name, desc etc.).
May be I need create Intent with AdGroupCriterion, not as separate logic? But CriterionCustomAffinity has no method for setting CustomAffinity.  

Real problem for me now is that you can not show me example for PHP. And there is no example in examples folder in lib.

I thought about analogy of BiddableAdGroupCriterion, where when I create Keyword I set it as criterion (Keyword extends Criterion) to BiddableAdGroupCriterion.
But with custom intent CustomAffinity not extends Criterion, so can not be set as criterion to AdGroupCriterion. I have CriterionCustomAffinity but there is only one method - set intent id, so intent till this moment must be created already.

Nadine, can you please contact to developers with my question. Because I am situation, when I can not understand how to use new feature, and in whole Internet is no examples how to do this. Way which I used with my own intuition works not correct, as you see.

My problem is simple. I created Custom Intent in account (I have all data about intent from AdWords response). I have ad group id. I need connect created intent and ad group.

Thank you!

Nadine Sundquist (AdWords API Team)

unread,
Jul 11, 2018, 9:44:22 AM7/11/18
to AdWords API and Google Ads API Forum
Hello Danny,

I do understand that you told me that you can create a Custom Intent in that account. However, the request ID you sent me and the error you sent me are tied to a request to create a Custom Intent failed. I was only debugging exactly what you sent me. Now, i'm guessing you may have accidentally sent me the incorrect request ID and error if it is indeed successful as you say it is. 

Could you please send me the other request ID and error that correspond with the request you're making to create the ad group criterion? It would be later in your logs than the request ID you sent me. That way I can verify how you're structuring your request and what the error is for that specific call.

Thanks,
Nadine, AdWords API Team
Message has been deleted

danny+...@pdffiller.com

unread,
Jul 12, 2018, 4:20:04 AM7/12/18
to AdWords API and Google Ads API Forum
For all who will has same problem as me. Here is solution:

Correct code :

In CustomAffinityService (initialized with Google\AdsApi\AdWords\v201806\rm\CustomAffinityService) you need create Custom Intent:

/**
 * $data example:
 *   [
 *       'test' => 'www.test.com',
 *       'test 2' => 'www.test2.com',
 *   ]
 *
 * @param array $data
 * @param string $audienceName
 * @return mixed
 */

public function addCustomIntentList(array $data, $audienceName)
{
    $keywordsList
= new CustomAffinity();


    $keywordsList
->setName($audienceName);
    $keywordsList
->setDescription(
        $audienceName
. ' created at ' . date('Y-m-d H:i:s')
   
);


    $keywordsList
->setType(
       
CustomAffinityType::CUSTOM_INTENT
   
);


    $keywordsList
->setTokens(self::createTokensList($data));


    $operation
= new CustomAffinityOperation();
    $operation
->setOperand($keywordsList);
    $operation
->setOperator(Operator::ADD);


   
return $this->mutateOperations([$operation], 'getEntries');
}


/**
 * Create a intent list rule composed of keywords/urls

 * @param array $data
 *
 * @return \Google\AdsApi\AdWords\v201806\rm\CustomAffinityToken[] $tokens
 */

private static function createTokensList(array $data)
{
    $items
= [];


   
foreach ($data as $name => $ruleItem) {
        $stringKey
= new CustomAffinityToken();
        $stringKey
->setParameter($ruleItem);
        $stringKey
->setTokenType(CustomAffinityTokenTokenType::URL);
        $stringKey
->setCustomAffinityId(1);


        $items
[] = $stringKey;
   
}


   
return $items;
}

And in AdGroupCriterionService (initialized with Google\AdsApi\AdWords\v201806\cm\AdGroupCriterionService) you need to connect Intent and AdGroup:

/**
 * $data example:
 *   [
 *       'AdGroupId' => 12345,
 *       'CustomIntentId' => 67890,
 *   ]
 *
 *
 * @param array $data
 * @return array
 * @throws AdWordsClientException
 */

public function createCustomIntentCriterion(array $data)
{

    $operations
= [];


   
foreach ($data as $item) {
       
if (!isset($item['AdGroupId'])) {
           
throw new AdWordsClientException('AdGroupId is not set');
       
}
       
if (!isset($item['CustomIntentId'])) {
           
throw new AdWordsClientException('CustomIntentId is not set');
       
}



        $intentListCriterion
= new CriterionCustomIntent();
        $intentListCriterion
->setCustomIntentId($item['CustomIntentId']);
        $intentListCriterion
->setCriterionType(CriterionType::CUSTOM_INTENT);



        $adGroupCriterion
= new BiddableAdGroupCriterion();
        $adGroupCriterion
->setAdGroupId($item['AdGroupId']);

        $adGroupCriterion
->setCriterion($intentListCriterion);


        $operation
= new AdGroupCriterionOperation();
        $operation
->setOperand($adGroupCriterion);
        $operation
->setOperator(Operator::ADD);


        $operations
[] = $operation;
   
}


   
return $this->mutateOperations($operations);
}

Error way is to try usage of BiddableAdGroupCriterion and AdGroupCriterionOperation not from AdGroupCriterionService.
Both of services extends same \Google\AdsApi\Common\AdsSoapClient but method mutateOperations() will has different endpoints in this 2 services, so generated SOAP for connecting intent to AdGroup will be incorrect if call  mutateOperations()  not from AdGroupCriterionService.

Nadine, thank for your support! Request can be closed.

Sincerely, Danny.
Reply all
Reply to author
Forward
0 new messages