Golang でGoogle Analytics からデータを引っ張ってくるサンプル


色々探したけどぱっと見つからなかったので。
既出かもしれませんが、ググラビリティが低かったです。

参考にしたものは
 - [Go Quickstart  |  Drive REST API  |  Google Developers](https://developers.google.com/drive/v3/web/quickstart/go)
 - [analytics - GoDoc](https://godoc.org/google.golang.org/api/analytics/v3)
 - [Dimensions & Metrics Explorer  |  Analytics Reporting API V4  |  Google Developers](https://developers.google.com/analytics/devguides/reporting/core/dimsmets)


まず、Google API Console でoauth用の認証トークンを発行する（割愛。参考資料の[Go Quickstart](https://developers.google.com/drive/v3/web/quickstart/go)を参照の事）

必要なパッケージ

```
$ go get -u google.golang.org/api/drive/v3
$ go get -u golang.org/x/oauth2/...
```


以下がおおまかなサンプルコードになります。

```go:sample.go

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "net/url"
    "os"
    "os/user"
    "path/filepath"

    "golang.org/x/net/context"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "google.golang.org/api/analytics/v3"
)


func getClient(ctx context.Context, config *oauth2.Config) *http.Client {
    cacheFile, err := tokenCacheFile()
    if err != nil {
        log.Fatalf("Unable to get path to cached credential file. %v", err)
    }
    token, err := tokenFromFile(cacheFile)
    if err != nil {
        token = getTokenFromWeb(config)
        saveToken(cacheFile,token)
    }

    return config.Client(ctx, token)
}

func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
    authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
    fmt.Printf("Go to the following link in your browser then type the authorization code : \n%v \n", authURL)
    var code string
    if _, err := fmt.Scan(&code); err != nil {
        log.Fatalf("Unable to read authorization code %v", err)
    }
    token, err := config.Exchange(oauth2.NoContext, code)
    if err != nil {
        log.Fatalf("Unable to retrieve toke from web %v", err)
    }
    return token

}

func tokenCacheFile() (string, error){
    usr, err := user.Current()
    if err != nil {
        return "", err
    }
    tokenCacheDir := filepath.Join(usr.HomeDir, ".credentials")
    os.MkdirAll(tokenCacheDir, 0700)
    return filepath.Join(tokenCacheDir, url.QueryEscape("google-api-tokens.json")), err

}


func tokenFromFile(file string) (*oauth2.Token, error) {
    f, err := os.Open(file)
    if err != nil {
        return nil, err
    }
    t := &oauth2.Token{}
    err = json.NewDecoder(f).Decode(t)
    defer f.Close()
    return t,err
}


func saveToken(file string, token *oauth2.Token) {
    fmt.Printf("Save credentials file to %s\n", file)
    f,err := os.Create(file)
    if err != nil {
        log.Fatalf("Unable to cache oauth token: %v", err)
    }
    defer f.Close()
    json.NewEncoder(f).Encode(token)
}

func main() {
    ctx := context.Background()

    b, err := ioutil.ReadFile("client_secret.json")
    if err != nil {
        log.Fatalf("Unable to read client secret file: %v", err)
    }
    config, err := google.ConfigFromJSON(b, analytics.AnalyticsReadonlyScope)
    if err != nil {
        log.Fatalf("Unable to read client secret file: %v", err)
    }
    client := getClient(ctx, config)


    // Google Analytics と接続するインスタンスの作成
    gasrv, err := analytics.New(client)
    if err != nil {
        log.Fatalf("Unable to Access Google Analytics: %v", err)
    }

    // アカウントが持つ全てのプロファイルIDを取得
    accounts, err := gasrv.Management.Accounts.List().Do()
    if err != nil {
        log.Fatalf("Unable to Get Accounts List: %v", err)
    }
    for _, account := range accounts.Items {
       properties, err := gasrv.Management.Webproperties.List(account.Id).Do()
       if err != nil {
            log.Fatalf("Error: %v", err)
        }
        for _, property := range properties.Items {
            profiles, err := gasrv.Management.Profiles.List(account.Id, property.Id).Do()
            if err != nil {
                log.Fatalf("Error: %v", err)
            }
            for _, profile := range profiles.Items {
                result, err := gasrv.Data.Ga.Get("ga:"+profile.Id, "7daysAgo", "today", "ga:sessions").Do()
                if err != nil {
                    log.Fatalf("もうエラー処理は嫌だ: %v",err)
                }
                fmt.Println("項目名: "+  result.ProfileInfo.ProfileName)
                fmt.Printf("Total Sessions: " + result.Rows[0][0]+"\n\n")
            }
        }
    }
}

```


以上になります。