/* * Copyright 2012 Nodeable Inc * * 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. */ package com.streamreduce.util; import com.google.api.client.auth.oauth2.TokenResponse; import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.jackson.JacksonFactory; import com.google.api.services.analytics.Analytics; import com.google.api.services.analytics.model.Account; import com.google.api.services.analytics.model.Accounts; import com.google.api.services.analytics.model.GaData; import com.google.api.services.analytics.model.Profile; import com.google.api.services.analytics.model.Profiles; import com.google.api.services.analytics.model.Webproperties; import com.google.api.services.analytics.model.Webproperty; import com.google.common.collect.Lists; import com.streamreduce.connections.GoogleAnalyticsProvider; import com.streamreduce.core.model.Connection; import com.streamreduce.core.service.exception.InvalidCredentialsException; import net.sf.json.JSONObject; import org.apache.commons.collections.CollectionUtils; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.io.IOException; import java.util.HashSet; import java.util.List; import java.util.Set; /** * <p>Author: Nick Heudecker</p> * <p>Created: 9/4/12 13:29</p> */ public class GoogleAnalyticsClient extends ExternalIntegrationClient { public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd"); private JacksonFactory jsonFactory = new JacksonFactory(); private NetHttpTransport transport = new NetHttpTransport(); private Analytics analytics; public GoogleAnalyticsClient(Connection connection) { super(connection); } @Override public void validateConnection() throws InvalidCredentialsException, IOException { List<JSONObject> profileIds = getProfiles(); if (CollectionUtils.isEmpty(profileIds)) { throw new InvalidCredentialsException("You must have one or more profiles defined in Google Analytics in order to continue."); } } public List<JSONObject> getProfiles() throws IOException { Analytics analytics = initializeAnalytics(); Accounts accounts = analytics.management().accounts().list().execute(); List<JSONObject> jsonProfiles = Lists.newArrayList(); if (accounts.getItems().isEmpty()) { System.err.println("No accounts found"); } else { for (Account account : accounts.getItems()) { String accountId = account.getId(); // Query webproperties collection. Webproperties webproperties = analytics.management().webproperties().list(accountId).execute(); if (webproperties.getItems().isEmpty()) { System.err.println("No Webproperties found"); } else { for (Webproperty webproperty : webproperties.getItems()) { String webpropertyId = webproperty.getId(); // Query profiles collection. Profiles profiles = analytics.management().profiles().list(accountId, webpropertyId).execute(); if (profiles.getItems().isEmpty()) { System.err.println("No profiles found"); } else { for (Profile profile : profiles.getItems()) { jsonProfiles.add(new JSONObjectBuilder() .add("id", profile.getId()) .add("name", profile.getName()) .build()); } } } } } } return jsonProfiles; } public JSONObject getProfileMetrics(String profileId) throws IOException { String formattedToday = DATE_TIME_FORMATTER.print(new DateTime()); Analytics analytics = initializeAnalytics(); GaData data = analytics.data().ga() .get("ga:" + profileId, formattedToday, formattedToday, "ga:visitors,ga:newVisits") .execute(); if (CollectionUtils.isEmpty(data.getRows())) { return null; } JSONObjectBuilder builder = new JSONObjectBuilder(); builder.add("id", profileId); int columnIndex = 0; for (GaData.ColumnHeaders header : data.getColumnHeaders()) { JSONObjectBuilder metric = new JSONObjectBuilder(); String metricName = normalizeMetricName(header.getName()); metric.add("metric", metricName); metric.add("id", profileId); Set<String> hashtags = new HashSet<>(); hashtags.add(metricName.toLowerCase()); for (List<String> row : data.getRows()) { for (int rowIndex = 0; rowIndex < row.size(); rowIndex++) { if (rowIndex == columnIndex) { metric.add("data", new Float(row.get(rowIndex))); } } } hashtags.add("googleanalytics"); metric.add("hashtags", hashtags); builder.append("metrics", metric.build()); columnIndex++; } return builder.build(); } public List<JSONObject> getAllProfileMetrics(Set<String> profileIds) throws IOException { List<JSONObject> allProfileMetrics = Lists.newArrayList(); for (String profileId : profileIds) { allProfileMetrics.add(getProfileMetrics(profileId)); } return allProfileMetrics; } private Analytics initializeAnalytics() { if (analytics == null) { GoogleAnalyticsProvider provider = new GoogleAnalyticsProvider(); TokenResponse tokenResponse = new TokenResponse().setRefreshToken(getConnectionCredentials().getOauthRefreshToken()); GoogleCredential credential = new GoogleCredential.Builder() .setJsonFactory(jsonFactory) .setTransport(transport) .setClientSecrets(provider.getClientId(), provider.getClientSecret()) .build() .setFromTokenResponse(tokenResponse); analytics = new Analytics.Builder(transport, jsonFactory, credential).build(); } return analytics; } private String normalizeMetricName(String name) { if (name.startsWith("ga:")) { return name.substring(3, name.length()); } else { return name; } } }