Posts under category Google

I am trying to implement App Tracking Transparency in my app. I tried to do this on first ViewControllor, but it crashes the app after uploading to the test flight.

After this, I found a lot of info that this should be done in appDelegate I did this way. Of course, I have set NSUserTrackingUsageDescription in Info.plist

I tried to figure it out with this post.

In the debugger, I always see "Not Determined". Could anyone please help with this?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {         // Override point for customization after application launch.         requestTrackingPermission()         GADMobileAds.sharedInstance().start(completionHandler: nil)         return true     } 

The function

func requestTrackingPermission() {       if #available(iOS 14, *) {         // ATTrackingManager.requestTrackingAuthorization { status in         ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in           switch status {           case .authorized:             // Tracking authorization dialog was shown             // and we are authorized             print("Authorized")                           // Now that we are authorized we can get the IDFA             print(ASIdentifierManager.shared().advertisingIdentifier)                          case .denied:             // Tracking authorization dialog was             // shown and permission is denied             print("Denied")           case .notDetermined:             // Tracking authorization dialog has not been shown             print("Not Determined")           case .restricted:             print("Restricted")           @unknown default:             print("Unknown")           }         }       )}     } 

I have configured a Google Ads DataTransfer stream from Google Ads to my GoogleBigQuery project. It runs, data flows, everything is fine. But when I decided to build a query that return an amount of money spend in the context of distinct combination of utm_marks (source, medium, campaign) I've faced a trouble with 'doublicated' data.

So, the query firstly goes to Adstat Table and takes the stats of every creativeId (I suppose creativeId means Ad) in every campaignId. Then it takes an every utm_marks from AdTrackingUrlTemplate of every creativeId from every campaign. Finally it merges two tables in one and in the output I have a full info about stats for every utm_mark.

Query looks like this:

 with   Adstat as (             select *              from `myproject.GoogleAds.AdStats_7394379271`         ),  Ad as (         select              CampaignId,              CreativeId,              REGEXP_EXTRACT(CreativeTrackingUrlTemplate, r"[?&]utm_source=([^&]+)") as source,             REGEXP_EXTRACT(CreativeTrackingUrlTemplate, r"[?&]utm_medium=([^&]+)") as medium,             REGEXP_EXTRACT(CreativeTrackingUrlTemplate, r"[?&]utm_campaign=([^&]+)") as campaign         from              `myproject.GoogleAds.p_Ad_7394379271`         where              CreativeTrackingUrlTemplate is not null          and              CreativeTrackingUrlTemplate!="{lpurl}"         group by              CampaignId, CreativeId, source, medium, campaign        ) select     date, CampaignId, CreativeId, impressions,      Clicks, Cost, Cost * 1.2/1000000 as adCost, source, medium, campaign from      Adstat  left join       Ad using (CampaignId, CreativeId) where      date = '2021-11-26' and      CampaignId = 1688777252 and      CreativeId = 328994634699 

output:

date CampaignId CreativeId impressions Clicks adCost source medium campaign
2021-11-26 1688777252 328994634699 1 1 10 google cpc _cntr_sale_15
2021-11-26 1688777252 328994634699 1 1 10 google cpc cntr_sale_16
2021-11-26 1688777252 328994634699 1 1 10 google cpc cntr_sale_17

And there is a trouble. If a creativeId during its lifetime has a several utm_marks in AdTrakingTemplate, all of them will go to result and all of them will receive a stats from AdStats Table (you can see at in output: same date, same CreativeAd, same stats, but different utms). So we have a double (triple,quadriple) impressions, clicks, amount spent etc. It's a pretty common case, because it's easier from manager to change a tracking template, than create a new Ad or Campaign in Google Ads.

And, unfortunatly, I don`t know, how to figure it out, cause there no way to determ which exactly utm_marks were in createiveIdTrakingTemplate when some stat actcions (impressions, click, etc) were performed.

Does anyone know, how to deal with it? Thanks for help!

App Engagement Campaigns that are present in the Google Analytics Interface are not present in BigQuery.

All other campaign data gets transferred to BigQuery.

Is there a specific reason for this behavior in the transfer job?

I would like to know, why these errors and how to solve them, when I use flutter run, flutter returns these errors:

Launching lib\main.dart on BISON in debug mode... Warning: Mapping new ns http://schemas.android.com/repository/android/common/02 to old ns http://schemas.android.com/repository/android/common/01 Warning: Mapping new ns http://schemas.android.com/repository/android/generic/02 to old ns http://schemas.android.com/repository/android/generic/01 Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/addon2/02 to old ns http://schemas.android.com/sdk/android/repo/addon2/01 Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/repository2/02 to old ns http://schemas.android.com/sdk/android/repo/repository2/01 Warning: Mapping new ns http://schemas.android.com/sdk/android/repo/sys-img2/02 to old ns http://schemas.android.com/sdk/android/repo/sys-img2/01 Formato de par�metros incorreto - Note: Some input files use or override a deprecated API. Note: Recompile with -Xlint:deprecation for details. Note: Some input files use unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. Note: C:\src\flutter\.pub-cache\hosted\pub.dartlang.org\path_provider_android-2.0.9\android\src\main\java\io\flutter\plugins\pathprovider\PathProviderPlugin.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. e: C:/Users/Arthur Alland/.gradle/caches/transforms-2/files-2.1/ae449724a6ca38888aadaf690b25af94/work-runtime-2.7.0-api.jar!/META-INF/work-runtime_release.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.1, expected version  is 1.1.15. FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:compileDebugKotlin'. > Compilation error. See log for more details * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 6m 1s Running Gradle task 'assembleDebug'...                            365,1s Exception: Gradle task assembleDebug failed with exit code 1 

Android Build Gradle

buildscript {     ext.kotlin_version = '1.3.50'     repositories {                                  google()                  jcenter()     }     dependencies {         classpath 'com.android.tools.build:gradle:4.1.0'         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"     } } allprojects {     repositories {         google()         jcenter()      } } rootProject.buildDir = '../build' subprojects {     project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects {     project.evaluationDependsOn(':app') } task clean(type: Delete) {     delete rootProject.buildDir } 

Gradle Wrapper Properties

distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip 

Android Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"     package="com.example.you_plan">     <!-- io.flutter.app.FlutterApplication is an android.app.Application that          calls FlutterMain.startInitialization(this); in its onCreate method.          In most cases you can leave this as-is, but you if you want to provide          additional functionality it is fine to subclass or reimplement          FlutterApplication and put your custom class here. -->     <application         android:name="io.flutter.app.FlutterApplication"         android:label="you_plan"         android:icon="@mipmap/ic_launcher">         <activity                      android:name=".MainActivity"                          android:launchMode="singleTop"             android:theme="@style/LaunchTheme"             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"             android:hardwareAccelerated="true"             android:windowSoftInputMode="adjustResize">             <!-- Specifies an Android theme to apply to this Activity as soon as                  the Android process has started. This theme is visible to the user                  while the Flutter UI initializes. After that, this theme continues                  to determine the Window background behind the Flutter UI. -->                           <meta-data               android:name="io.flutter.embedding.android.NormalTheme"               android:resource="@style/NormalTheme"               />             <!-- Displays an Android View that continues showing the launch screen                  Drawable until Flutter paints its first frame, then this splash                  screen fades out. A splash screen is useful to avoid any visual                  gap between the end of Android's launch screen and the painting of                  Flutter's first frame. -->             <meta-data               android:name="io.flutter.embedding.android.SplashScreenDrawable"               android:resource="@drawable/launch_background"               />                         <intent-filter>                 <action android:name="android.intent.action.MAIN"/>                 <category android:name="android.intent.category.LAUNCHER"/>             </intent-filter>         </activity>         <!-- Don't delete the meta-data below.              This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->         <meta-data             android:name="flutterEmbedding"             android:value="2" />               <meta-data     android:name="com.google.android.gms.ads.APPLICATION_ID"     android:value="ca-app-pub-3940256099942544~3347511713"/>     </application> </manifest>

I googled it several times and the problem seems to be with these android files, but I don't have much experience with android

I'm making Web Application for Extracting data from Youtube Videos then analyze it and find the best keywords

All I need is finding the best keywords from Keywords Planner of Google depends on the volume search i did extract the youtube video data, I followed this library https://github.com/googleads/googleads-php-lib

I have Clientid, Clientsecret and Developer Token After I installed the library successfully and tried to test GetCampaigns() class, I get this Error

Fatal error: Uncaught InvalidArgumentException: All of 'clientId', 'clientSecret', and 'refreshToken' must be set when using installed/web application flow. in C:\xampp\htdocs\seosystem\googleads-php-lib\src\Google\AdsApi\Common\OAuth2TokenBuilder.php:225 Stack trace: #0 C:\xampp\htdocs\seosystem\googleads-php-lib\src\Google\AdsApi\Common\OAuth2TokenBuilder.php(173): Google\AdsApi\Common\OAuth2TokenBuilder->validate() #1 C:\xampp\htdocs\seosystem\googleads-php-lib\examples\AdWords\v201809\BasicOperations\GetCampaigns.php(81): Google\AdsApi\Common\OAuth2TokenBuilder->build() #2 C:\xampp\htdocs\seosystem\googleads-php-lib\examples\AdWords\v201809\BasicOperations\GetCampaigns.php(90): Google\AdsApi\Examples\AdWords\v201809\BasicOperations\GetCampaigns::main() #3 C:\xampp\htdocs\seosystem\index.php(4): require_once('C:\\xampp\\htdocs...') #4 {main} thrown in C:\xampp\htdocs\seosystem\googleads-php-lib\src\Google\AdsApi\Common\OAuth2TokenBuilder.php on line 225 

I went to OAuth2TokenBuilder and replaced and still get the same Error Message no worries i'll change the key later

 private $clientId ='847786194979-n0udvkdi41r9fd5arlma6gadlm2kueot.apps.googleusercontent.com'; private $clientSecret ='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'; private $refreshToken ='Af8L57gifnGl1b4M324_Tg'; 

and this's the whole file

<?php /**  * Copyright 2016 Google Inc. All Rights Reserved.  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *     http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ namespace Google\AdsApi\Common; use Google\Auth\Credentials\ServiceAccountCredentials; use Google\Auth\Credentials\UserRefreshCredentials; use InvalidArgumentException; /**  * Builds OAuth2 access token fetchers.  *  * @see FetchAuthTokenInterface  */ final class OAuth2TokenBuilder implements AdsBuilder{     private $configurationLoader;     private $jsonKeyFilePath;     private $scopes;     private $impersonatedEmail;     private $clientId ='847786194979-n0udvkdi41r9fd5arlma6gadlm2kueot.apps.googleusercontent.com';     private $clientSecret ='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';     private $refreshToken ='Af8L57gifnGl1b4M324_Tg';     public function __construct(){         $this->configurationLoader = new ConfigurationLoader();     }     /**      * Reads configuration settings from the specified filepath. The filepath is      * optional, and if omitted, it will look for the default configuration      * filename in the home directory of the user running PHP.      *      * @see AdsBuilder::DEFAULT_CONFIGURATION_FILENAME      *      * @param string $path the filepath      * @return OAuth2TokenBuilder this builder populated from the configuration      * @throws InvalidArgumentException if the configuration file could not be      *     found      */     public function fromFile($path = null){         if ($path === null) {             $path = self::DEFAULT_CONFIGURATION_FILENAME;         }         return $this->from($this->configurationLoader->fromFile($path));     }     /**      * @see AdsBuilder::from()      */     public function from(Configuration $configuration){         $this->jsonKeyFilePath = $configuration->getConfiguration('jsonKeyFilePath', 'OAUTH2');         $this->scopes = $configuration->getConfiguration('scopes', 'OAUTH2');         $this->impersonatedEmail = $configuration->getConfiguration('impersonatedEmail', 'OAUTH2');         $this->clientId = $configuration->getConfiguration('clientId', 'OAUTH2');         $this->clientSecret = $configuration->getConfiguration('clientSecret', 'OAUTH2');         $this->refreshToken = $configuration->getConfiguration('refreshToken', 'OAUTH2');         return $this;     }     /**      * Includes an absolute path to an OAuth2 JSON key file when using service      * account flow. Required and only applicable when using service account flow.      *      * @param string|null $jsonKeyFilePath      * @return OAuth2TokenBuilder this builder      */     public function withJsonKeyFilePath($jsonKeyFilePath){         $this->jsonKeyFilePath = $jsonKeyFilePath;         return $this;     }     /**      * Includes OAuth2 scopes. Required and only applicable when using service      * account flow.      *      * @param string|null $scopes a space-delimited list of scopes      * @return OAuth2TokenBuilder this builder      */     public function withScopes($scopes){         $this->scopes = $scopes;         return $this;     }     /**      * Includes an email of account to impersonate when using service account      * flow. Optional and only applicable when using service account flow.      *      * @param string|null $impersonatedEmail      * @return OAuth2TokenBuilder this builder      */     public function withImpersonatedEmail($impersonatedEmail){         $this->impersonatedEmail = $impersonatedEmail;         return $this;     }     /**      * Includes an OAuth2 client ID. Required when using installed application or      * web application flow.      *      * @param string|null $clientId      * @return OAuth2TokenBuilder this builder      */     public function withClientId($clientId){         $this->clientId = $clientId;         return $this;     }     /**      * Includes an OAuth2 client secret. Required when using installed application      * or web application flow.      *      * @param string|null $clientSecret      * @return OAuth2TokenBuilder this builder      */     public function withClientSecret($clientSecret){         $this->clientSecret = $clientSecret;         return $this;     }     /**      * Includes an OAuth2 refresh token. Required when using installed application      * or web application flow.      *      * @param string|null $refreshToken      * @return OAuth2TokenBuilder this builder      */     public function withRefreshToken($refreshToken){         $this->refreshToken = $refreshToken;         return $this;     }     /**      * @see AdsBuilder::build()      */     public function build(){         $this->defaultOptionals();         $this->validate();         if ($this->jsonKeyFilePath !== null) {             return new ServiceAccountCredentials(                 $this->scopes,                 $this->jsonKeyFilePath,                 $this->impersonatedEmail             );         } else {             return new UserRefreshCredentials(                 null,                 [                     'client_id' => $this->clientId,                     'client_secret' => $this->clientSecret,                     'refresh_token' => $this->refreshToken                 ]             );         }     }     /**      * @see AdsBuilder::defaultOptionals()      */     public function defaultOptionals(){         // Nothing to default for this builder.     }     /**      * @see AdsBuilder::validate()      */     public function validate(){         if (($this->jsonKeyFilePath !== null || $this->scopes !== null)             && ($this->clientId !== null || $this->clientSecret !== null                 || $this->refreshToken !== null)) {             throw new InvalidArgumentException(                 'Cannot have both service account '                 . 'flow and installed/web application flow credential values set.'             );         }         if ($this->jsonKeyFilePath !== null || $this->scopes !== null) {             if ($this->jsonKeyFilePath === null || $this->scopes === null) {                 throw new InvalidArgumentException(                     'Both \'jsonKeyFilePath\' and '                     . '\'scopes\' must be set when using service account flow.'                 );             }         } elseif ($this->clientId === null             || $this->clientSecret === null             || $this->refreshToken === null) {             throw new InvalidArgumentException(                 'All of \'clientId\', '                 . '\'clientSecret\', and \'refreshToken\' must be set when using '                 . 'installed/web application flow.'             );         }     }     /**      * Gets the JSON key file path.      *      * @return string|null      */     public function getJsonKeyFilePath(){         return $this->jsonKeyFilePath;     }     /**      * Gets the scopes.      *      * @return string|null      */     public function getScopes(){         return $this->scopes;     }     /**      * Gets the impersonated email.      *      * @return string|null      */     public function getImpersonatedEmail(){         return $this->impersonatedEmail;     }     /**      * Gets the client ID.      *      * @return string|null      */     public function getClientId(){         return $this->clientId;     }     /**      * Gets the client secret.      *      * @return string|null      */     public function getClientSecret(){         return $this->clientSecret;     }     /**      * Gets the refresh token.      *      * @return string|null      */     public function getRefreshToken(){         return $this->refreshToken;     } }