Search code examples
pythongoogle-analyticsoauthgoogle-analytics-api

Manage an Analytics Account with OAuth and Google Analytics Admin API


I'm trying to use the Google Analytics Admin API to access properties and manage settings (trying to link Google Analytics and Google Ads when a client requests that we manage their ads). Ideally this would be done through OAuth and them granting access right from the browser when they sign up. However, if there's a way to send an management invite like with Google Ads accounts that would work too.

I tried setting up a service account but couldn't figure out how to give it access to an account. Then I tried granting access using OAuth, which I was able to get a token from but I'm not able to use that token with the AnalyticsAdminServiceClient library (or at least can't figure out how).

Here's what I tried with OAuth:

import yaml
from google.analytics.admin import AnalyticsAdminServiceClient

yaml_file = open('./oauth_analytics.yaml')
parsed_yaml_file = yaml.load(yaml_file, Loader=yaml.FullLoader)

test_auth_code = parsed_yaml_file['test_auth_code']
client_id = parsed_yaml_file['client_id']
client_secret = parsed_yaml_file['client_secret']

#get a refresh token
from google.oauth2.credentials import Credentials

credentials = Credentials(
    None,
    refresh_token=test_auth_code,
    token_uri="https://oauth2.googleapis.com/token",
    client_id=client_id,
    client_secret=client_secret
)

# Use the refresh token to obtain an access token.
client = AnalyticsAdminServiceClient(credentials=credentials)

print(client.list_accounts())

\When I run that code I get the following exception:

google.api_core.exceptions.Unauthenticated: 401 Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.

I found this question answer which shows the same method I'm using (but I'm assuming it worked for them, there's probably something obvious I'm missing): How do I call Google Analytics Admin API (for GA4) using an OAuth2 client in node.js?


Solution

  • If you want to use Oauth2 instead of a service account your code should look more like this

    from google.analytics.admin import AnalyticsAdminServiceClient
    
    # pip install google-analytics-admin
    
    CREDENTIALS_FILE_PATH = 'C:\Development\FreeLance\GoogleSamples\Credentials\credentials.json'
    GA4_PROPERTY_ID = '250796939'
    
    from google_auth_oauthlib import flow
    
    def list_accounts(credentials=None):
        """
        Lists the available Google Analytics accounts.
    
        Args:
    
        """
        # Using a default constructor instructs the client to use the credentials
        # specified in GOOGLE_APPLICATION_CREDENTIALS environment variable.
        client = AnalyticsAdminServiceClient(credentials=credentials)
    
        request = AnalyticsAdminServiceClient.ListAccountSummariesRequest()
        request.page_size = 1
    
        # Make the request
        results = client.list_account_summaries(page_size = 1)
    
        # Displays the configuration information for all Google Analytics accounts
        # available to the authenticated user.
        print("Result:")
        for account in results:
            print(account)
    
    def get_credentials():
        """Creates an OAuth2 credentials instance."""
    
        appflow = flow.InstalledAppFlow.from_client_secrets_file(
            CREDENTIALS_FILE_PATH,
            scopes=["https://www.googleapis.com/auth/analytics.readonly"],
        )
        # TODO(developer): Update the line below to set the `launch_browser` variable.
        # The `launch_browser` boolean variable indicates if a local server is used
        # as the callback URL in the auth flow. A value of `True` is recommended,
        # but a local server does not work if accessing the application remotely,
        # such as over SSH or from a remote Jupyter notebook.
        launch_browser = True
        if launch_browser:
            appflow.run_local_server()
        else:
            # note yes this is deprecated.  It will work if you change the redirect uri in the url given you from urn:ietf:wg:oauth:2.0:oob
            # to http://127.0.0.1  The client library team needs to fix this.
            appflow.run_console()
        return appflow.credentials
    
    
    
    def main():
        credentials = get_credentials()
        list_accounts(credentials)
    
    if __name__ == "__main__":
        main()