Mengisi Nilai yang Hilang dari Permintaan Tanggal

Nick Mihailovski, Tim Google Analytics API – Oktober 2009

Artikel ini membahas cara mendeteksi dan mengisi ulang nilai deret waktu yang tidak ada dalam data yang ditampilkan dari Data Export API Google Analytics.


Sebelum Memulai

Artikel ini mengasumsikan bahwa Anda mengetahui cara kerja Google Analytics Data Export API. Kode contoh berada dalam Java, tetapi Anda dapat menggunakan konsep dalam bahasa pilihan Anda. Kode untuk artikel ini disediakan sebagai open source dan dapat didownload dari hosting project.

Setelah membaca artikel ini, Anda akan mempelajari:

  • Cara Google Analytics Data Export API memperlakukan dimensi tanggal.
  • Cara menyusun kueri untuk mengelompokkan hasil dan mendeteksi tanggal yang tidak ada.
  • Cara mengisi nilai yang hilang menggunakan Java.

Pengantar

Membandingkan data pada periode waktu tertentu memberikan konteks. Misalnya, menyatakan bahwa sebuah situs menghasilkan pendapatan sebesar $1 juta tidak berarti banyak. Namun, menyatakan bahwa sebuah situs meningkatkan pendapatan sebesar 10x kuartal ke kuartal atau year over year memang mengesankan. Dengan Google Analytics API, Anda dapat dengan mudah memetakan data dari waktu ke waktu menggunakan dimensi ga:date, ga:day, dan ga:month.

Jika kueri Anda hanya menggunakan dimensi tanggal, jika ada hari dalam rentang tanggal yang mengumpulkan data nol, Google Analytics API akan mengisi ulang tanggal dan nilai 0 untuk metrik.

ga:datega:sessions
2010-03-01101
2010-03-020
2010-03-0369

Namun, hal itu akan menjadi rumit jika Anda mengkueri tanggal beserta dimensi lainnya. Jika salah satu tanggal tidak memiliki data, API TIDAK akan menampilkan entri untuk tanggal tersebut. Fungsi ini akan langsung menuju ke tanggal berikutnya yang tersedia yang berisi data.

ga:keywordga:datega:sessions
kursi2010-03-0155
kursi2010-03-0348

Idealnya, analis ingin mengisikan tanggal untuk kata kunci tertentu seperti contoh pertama di atas

Artikel ini menjelaskan beberapa praktik terbaik untuk pengisian ulang data secara pragmatis.

Latar belakang

Mari kita lihat mengapa masalah ini terjadi. Ada 2 alasan.

  1. Google Analytics hanya memproses data yang dikumpulkan. Jika tidak ada yang mengunjungi situs pada hari tertentu, maka tidak ada data untuk diproses, sehingga tidak ada data yang ditampilkan.
  2. Sangat sulit untuk menentukan berapa banyak dimensi tambahan dan nilai apa yang harus digunakan untuk tanggal yang tidak memiliki data.

Jadi, daripada mencoba menentukan satu proses untuk mengatur semuanya, Google Analytics API menyerahkan proses pengisian data untuk kueri yang memiliki beberapa dimensi kepada developer. Anda yang Beruntung :)

Ringkasan Program

Berikut adalah langkah-langkah untuk mengisi ulang data pada diagram di atas.

  1. Ubah kueri untuk memastikan dimensi diurutkan secara oportunistik.
  2. Tentukan perkiraan tanggal dari rentang tanggal.
  3. Lakukan iterasi dan isi ulang tanggal yang hilang.
  4. Isi nilai yang belum diisi yang tersisa.

Mengubah Kueri

Untuk mengisi ulang tanggal, kita perlu memastikan bahwa data yang ditampilkan dari API menggunakan format yang memudahkan deteksi jika tanggal tidak ada. Berikut adalah contoh kueri untuk mengambil ga:keyword dan ga:date selama 5 hari pertama pada bulan Maret:

DataQuery dataQuery = new DataQuery(new URL(BASE_URL));
dataQuery.setIds(TABLE_ID);
dataQuery.setStartDate("2010-03-01");
dataQuery.setEndDate("2010-03-05");
dataQuery.setDimensions("ga:keyword,ga:date");
dataQuery.setMetrics("ga:entrances");

Setelah kueri dikirim ke API, hasilnya akan berisi daftar objek DataEntry. Setiap objek entri mewakili baris data dan menyertakan nama serta nilai untuk dimensi/metrik. Karena tidak ada parameter pengurutan yang digunakan, hasilnya ditampilkan dalam urutan arbitrer.

ga:keywordga:datega:entrances
kursi2010-03-0414
kursi2010-03-0123
meja2010-03-0418
meja2010-03-0224
kursi2010-03-0313

Untuk memudahkan mengidentifikasi tanggal mana yang tidak ada, kita harus mengelompokkan semua dimensi terlebih dahulu. Hal ini dapat dilakukan dengan menetapkan parameter pengurutan kueri ke dimensi yang digunakan dalam kueri asli.

dataQuery.setSort("ga:keyword,ga:date");

Menambahkan parameter pengurutan akan membuat API menampilkan hasil dalam urutan yang diinginkan.

ga:keywordga:datega:entrances
kursi2010-03-0123
kursi2010-03-0313
kursi2010-03-0414
meja2010-03-0224
meja2010-03-0418

Langkah kedua adalah memastikan bahwa untuk setiap dimensi, semua tanggal ditampilkan dalam urutan menaik. Meskipun Google Analytics API menyediakan sejumlah dimensi tanggal, hanya ga:date yang dapat diurutkan secara akurat di seluruh batas tanggal (yaitu hari, bulan, tahun). Jadi, jika Anda ingin mengisi ulang tanggal, pastikan kueri Anda menggunakan dimensi ga:date dalam dimensi dan parameter kueri pengurutan.

Setelah kueri yang diurutkan dijalankan, semua halaman landing yang sama akan ditampilkan berdampingan dan tanggalnya akan berurutan. Daftar tanggal untuk satu halaman landing dapat dianggap sebagai deret waktu dan karena tanggal tersebut berurutan, akan jauh lebih mudah untuk mengidentifikasi tanggal yang tidak ada.

Tentukan Perkiraan Tanggal

Untuk mendeteksi tanggal yang tidak ada, kita perlu membandingkan tanggal sebenarnya yang ditampilkan dari API dengan tanggal yang diharapkan dalam setiap deret waktu. Kita dapat mengetahui apa yang diharapkan dengan:

  1. Menentukan tanggal mulai yang diharapkan dari kueri API.
  2. Menghitung jumlah hari yang diharapkan dalam rentang tanggal kueri.

Kedua nilai dapat digunakan bersama untuk menentukan setiap tanggal yang diharapkan dengan menambahkan 1 tanggal mulai untuk setiap hari dalam rentang tanggal tersebut.

Menentukan Tanggal Mulai yang Diharapkan

Kita dapat menggunakan parameter kueri start-date sebagai tanggal mulai rangkaian yang diharapkan. Karena format tanggal yang ditampilkan dalam yyyyMMdd respons API berbeda dengan format parameter kueri yyyy-MM-dd, kita harus mengonversi format tanggal terlebih dahulu sebelum dapat menggunakannya.

Metode setExpectedStartDate mengonversi format tanggal.

  private static SimpleDateFormat queryDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  private static SimpleDateFormat resultDateFormat = new SimpleDateFormat("yyyyMMdd");

  public void setExpectedStartDate(String startDate) {
    try {
      calendar.setTime(queryDateFormat.parse(startDate));
      expectedStartDate = resultDateFormat.format(calendar.getTime());
    } catch (ParseException e) {
      handleException(e);
    }
  }

Menghitung Jumlah Hari yang Diharapkan

Untuk mendapatkan jumlah hari dalam rentang tanggal, program ini mengurai tanggal mulai dan akhir menjadi objek Date Java. Kemudian menggunakan objek Calendar untuk mencari tahu waktu di antara kedua tanggal. Satu hari ditambahkan ke selisih pada tanggal untuk membuat hitungan inklusif.

  private static final long millisInDay = 24 * 60 * 60 * 1000;

  public void setNumberOfDays(DataQuery dataQuery) {
    long startDay = 0;
    long endDay = 0;

    try {
      calendar.setTime(queryDateFormat.parse(dataQuery.getStartDate()));
      startDay = calendar.getTimeInMillis() / millisInDay;

      calendar.setTime(queryDateFormat.parse(dataQuery.getEndDate()));
      endDay = calendar.getTimeInMillis() / millisInDay;
    } catch (ParseException e) {
      handleException(e);
    }

    numberOfDays = (int) (endDay - startDay + 1);
  }

Sekarang kita memiliki semua data yang diperlukan untuk mencari tahu tanggal mana yang tidak ada.

Mengidentifikasi Setiap Deret Waktu dalam Hasil

Setelah kueri dieksekusi, program akan melalui setiap objek DataEntry dalam respons API. Karena kueri awalnya diurutkan, respons akan memiliki deret waktu parsial untuk setiap kata kunci. Jadi kita perlu menemukan awal dari setiap deret waktu, lalu memeriksa setiap tanggal dan mengisi data yang hilang yang tidak ditampilkan oleh API.

Program ini menggunakan variabel dimensionValue dan tmpDimensionValue untuk mendeteksi awal setiap rangkaian.

Berikut adalah seluruh kode untuk menangani respons. Mengisi data yang hilang dibahas di bawah ini.

public void printBackfilledResults(DataFeed dataFeed) {
  String expectedDate = "";
  String dimensionValue = "";
  List<Integer> row = null;

  for (DataEntry entry : dataFeed.getEntries()) {
    String tmpDimValue = entry.getDimensions().get(0).getValue();

    // Detect beginning of a series.
    if (!tmpDimValue.equals(dimensionValue)) {
      if (row != null) {
        forwardFillRow(row);
        printRow(dimensionValue, row);
      }

      // Create a new row.
      row = new ArrayList<Integer>(numberOfDays);
      dimensionValue = tmpDimValue;
      expectedDate = expectedStartDate;
    }

    // Backfill row.
    String foundDate = entry.getDimension("ga:date").getValue();
    if (!foundDate.equals(expectedDate)) {
      backFillRow(expectedDate, foundDate, row);
    }

    // Handle the data.
    Metric metric = entry.getMetrics().get(0);
    row.add(new Integer(metric.getValue()));
    expectedDate = getNextDate(foundDate);
  }

  // Handle the last row.
  if (row != null) {
    forwardFillRow(row);
    printRow(dimensionValue, row);
  }
}

Isi Ulang Tanggal yang Tidak Ada

Untuk setiap entri dalam sebuah deret, program akan menyimpan nilai metrik (masuk) dalam ArrayList yang disebut row. Saat deret waktu baru terdeteksi, baris baru akan dibuat dan tanggal yang diharapkan ditetapkan ke tanggal mulai yang diharapkan.

Kemudian untuk setiap entri, program akan memeriksa apakah nilai tanggal dalam entri sama dengan tanggal yang diharapkan. Jika sama, metrik di entri ditambahkan ke baris. Jika tidak, program mendeteksi tanggal yang tidak ada yang perlu diisi ulang.

Metode backfillRow menangani pengisian ulang data. Kolom ini menerima sebagai parameter, tanggal yang diharapkan dan ditemukan, serta baris saat ini. Kemudian, metode ini menentukan jumlah hari antara kedua tanggal tersebut (non-inklusif) dan menambahkan angka 0 tersebut ke baris.

  public void backFillRow(String startDate, String endDate, List<Integer> row) {
    long d1 = 0;
    long d2 = 0;

    try {
      calendar.setTime(resultDateFormat.parse(startDate));
      d1 = calendar.getTimeInMillis() / millisInDay;

      calendar.setTime(resultDateFormat.parse(endDate));
      d2 = calendar.getTimeInMillis() / millisInDay;

    } catch (ParseException e) {
      handleException(e);
    }

    long differenceInDays = d2 - d1;
    if (differenceInDays > 0) {
      for (int i = 0; i < differenceInDays; i++) {
        row.add(0);
      }
    }
  }

Setelah metode ini selesai, baris telah diisi ulang dengan data dan data saat ini dapat ditambahkan. Tanggal yang diharapkan kemudian bertambah menjadi satu hari setelah tanggal yang ditemukan menggunakan metode getNextDate.

public String getNextDate(String initialDate) {
  try {
    calendar.setTime(resultDateFormat.parse(initialDate));
    calendar.add(Calendar.DATE, 1);
    return resultDateFormat.format(calendar.getTime());

  } catch (ParseException e) {
    handleException(e);
  }
  return "";
}

Isi Nilai yang Tersisa

Setelah data seri diproses menjadi row, kita harus memeriksa bahwa tidak ada lagi tanggal yang hilang di akhir seri.

Metode forwardFillRow hanya menghitung perbedaan antara jumlah hari dalam kueri asli dengan ukuran baris saat ini, dan menambahkan angka 0 tersebut ke akhir baris.

public void forwardFillRow(List<Integer> row) {
  int remainingElements = numberOfDays - row.size();
  if (remainingElements > 0) {
    for (int i = 0; i < remainingElements; i++) {
      row.add(0);
    }
  }
}

Pada tahap ini, program telah mengisi nilai yang hilang dalam deret waktu. Setelah kita memiliki semua data, program akan mencetak nilai dimensi dan metrik sebagai daftar yang dipisahkan koma.

Kesimpulan

Dengan contoh ini, Anda dapat dengan mudah mengisi ulang data pada tanggal yang tidak ditampilkan oleh API. Seperti yang disebutkan di atas, solusi ini dapat disesuaikan dengan bahasa pemrograman apa pun. Developer bahkan dapat menyesuaikan teknik ini dan menerapkannya untuk menangani berbagai dimensi dan metrik. Kini, mulai lebih mudah untuk mulai melakukan analisis lanjutan pada deret waktu yang ditampilkan oleh Google Analytics API.