Skip to content

Commit

Permalink
Filter parity with iOS + ecomm analytics
Browse files Browse the repository at this point in the history
* filter parity with iOS

* sort type consitency

* add analytics class supporting ATC and Conversion methods, update readme, update example app

* PR changes

* ints

* update examples

* pdp albums set album_id
  • Loading branch information
kj13ennett authored Jul 17, 2019
1 parent 6a855de commit 5b53805
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 39 deletions.
48 changes: 47 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ PXLAlbumFilterOptions filterOptions = new PXLAlbumFilterOptions();
filterOptions.minTwitterFollowers = 1000;
filterOptions.minInstagramFollowers = 2000;
PXLAlbumSortOptions sortOptions = new PXLAlbumSortOptions();
sortOptions.sortType = PXLAlbumSortType.PHOTORANK;
sortOptions.sortType = PXLAlbumSortType.DYNAMIC;
sortOptions.descending = true;
album.setPerPage(15);
album.setFilterOptions(filterOptions);
Expand All @@ -83,6 +83,52 @@ To fire an opened ligtbox event, simply call the `openedLightbox` method of the
photo.openedLightbox(context);
```

### Ecommerce Analytics

For triggering all ecommerce analytics events within your app, you'll want to use the `PXLAnalytics` class. Instantiate one with the application context:
```
#!Java
Context c = this.getApplicationContext();
PXLAnalytics pixleeAnalytics = new PXLAnalytics(c);
```

#### Add To Cart
To fire an Add To Cart event, simply call the `addToCart` method of the PXLAnalytics object with the necessary parameters, and an "Add To Cart" event will be fired containing all of the necessary analytics information.
The parameters for this method are:
- [Required] sku (String)
- [Required] price (String)
- [Required] quantity (Integer)
- [Optional] currency (String)

```
#!java
pixleeAnalytics.addToCart("sku123", "123", 4);
```

#### Conversion
To fire a Conversion event, simply call the `conversion` method of the PXLAnalytics object with the necessary parameters, and a "Conversion" event will be fired containing all of the necessary analytics information.
The parameters for this method are:
- [Required] cartContents (ArrayList<HashMap<String, Object>>)
- [Required] cartTotal (String)
- [Required] cartTotalQuantity (Integer)
- [Optional] orderId (String)
- [Optional] currency (String)

```
#!java
ArrayList<HashMap<String, Object>> cartContents = new ArrayList();
HashMap<String, Object> cart1 = new HashMap();
cart1.put("price", "123");
cart1.put("product_sku", "test123");
cart1.put("quantity", "4");
cartContents.add(cart1);
pixleeAnalytics.conversion(cartContents, "123", 4);
```

To help you get up and running quickly, we've also built an sample application featuring a grid view, list view, and detail view. The adapters simply maintain an ArrayList of PXLPhoto, which is updated via calls to `loadNextPageOfPhotos`. Since the data source contains the full PXLPhoto object, you can easily customize your own widgets to display the desired images and text. The sample also implements a scroll listener which times calls to `loadNextPageOfPhotos` to provide the endless scroll effect.
An example of the proper usage of an opened lightbox event is also included in the sample app!

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.pixlee.pixleesdk.PXLAlbum;
import com.pixlee.pixleesdk.PXLAnalytics;
import com.pixlee.pixleesdk.PXLContentSource;
import com.pixlee.pixleesdk.PXLContentType;
import com.pixlee.pixleesdk.PXLPdpAlbum;
import com.pixlee.pixleesdk.PXLAlbumFilterOptions;
import com.pixlee.pixleesdk.PXLAlbumSortOptions;
Expand All @@ -26,8 +29,11 @@
import com.pixlee.pixleesdk.PXLPhoto;
import com.pixlee.pixleesdk.PXLPhotoSize;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class SampleActivity extends AppCompatActivity implements PXLAlbum.RequestHandlers {
private ArrayList<PXLPhoto> photoList;
Expand Down Expand Up @@ -173,6 +179,55 @@ private void createAlbum() {
PXLAlbumFilterOptions fo = new PXLAlbumFilterOptions();
fo.minTwitterFollowers = 0;
fo.minInstagramFollowers = 0;

/* ~~~ content source and content filter examples ~~~
ArrayList contentSource = new ArrayList();
contentSource.add(PXLContentSource.INSTAGRAM);
fo.contentSource = contentSource;
ArrayList contentType = new ArrayList();
contentType.add(PXLContentType.IMAGE);
fo.contentType = contentType;
*/


/* ~~~ date filter examples ~~~
fo.submittedDateEnd = new Date(2019, 7, 16);
fo.submittedDateStart = new Date(2019, 7, 17);
*/


// fo.filterByRadius = "21.3069,-157.8583,20"; radius filter example


/* ~~~ in_categories filter example ~~~
ArrayList incategories = new ArrayList<Integer>();
incategories.add(1234);
incategories.add(5678);
fo.inCategories = incategories;
*/

/* ~~~ filter_by_userhandle filter example ~~~
HashMap userHandleFilter = new HashMap<String, Object> ();
userHandleFilter.put("contains", new String[] {"test1", "test2"});
fo.filterByUserhandle = userHandleFilter;
*/

/* ~~~ computer_vision filter example ~~~
HashMap computerVisionFilter = new HashMap<String, Object> ();
computerVisionFilter.put("contains", new String[] {"hat"});
fo.computerVision = computerVisionFilter;
*/


// fo.hasProduct = false;
// fo.hasPermission = false;
// fo.inStockOnly = false;

PXLAlbumSortOptions so = new PXLAlbumSortOptions();
so.sortType = PXLAlbumSortType.RECENCY;
so.descending = true;
Expand All @@ -191,6 +246,7 @@ private void loadMorePhotos() {
}

private void updateDetailView(PXLPhoto photo) {
Context c = this.getApplicationContext();
this.detailSourceIcon.setImageResource(photo.sourceIconImage());
this.detailImage.setImageUrl(photo.getUrlForSize(PXLPhotoSize.MEDIUM).toString(), PXLClient.getInstance(this).getImageLoader());
this.detailText.setText(photo.photoTitle);
Expand Down Expand Up @@ -220,7 +276,29 @@ private void updateDetailView(PXLPhoto photo) {
} else {
actionLinksLayout.setVisibility(View.GONE);
}
photo.openedLightbox(getApplicationContext());

photo.openedLightbox(c); // Opened Lightbox Analytics Example

/* ~~~ Add to cart analytics example ~~~
PXLAnalytics pixleeAnalytics = new PXLAnalytics(c);
pixleeAnalytics.addToCart("sku123", "123", 4);
*/


/* ~~~ Conversion analytics example ~~~
ArrayList<HashMap<String, Object>> cartContents = new ArrayList();
HashMap<String, Object> cart1 = new HashMap();
cart1.put("price", "123");
cart1.put("product_sku", "test123");
cart1.put("quantity", "4");
cartContents.add(cart1);
pixleeAnalytics.conversion(cartContents, "123", 4);
*/

this.populateDetailActions(photo);
}

Expand Down
5 changes: 4 additions & 1 deletion pixleesdk/src/main/java/com/pixlee/pixleesdk/PXLAlbum.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public void JsonReceived(JSONObject response) {
this.page = response.getInt("page");
this.perPage = response.getInt(("per_page"));
this.hasMore = response.getBoolean(("next"));
if(this.id == null){
this.id = String.valueOf(response.getInt("album_id"));
}
//add placeholders for photos if they haven't been loaded yet
if (this.photos.size() < (this.page - 1) * this.perPage) {
for (int i = this.photos.size(); i < (this.page - 1) * this.perPage; i++) {
Expand Down Expand Up @@ -199,7 +202,7 @@ public boolean openedWidget() {
}

try{
body.put("album_id", this.id);
body.put("album_id", Integer.parseInt(this.id));
body.put("per_page", this.perPage);
body.put("page", this.page);
body.put("photos", stringBuilder.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

import java.util.ArrayList;
import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;

/***
* Represents the filter options for a PXLAlbum. Initialize an instance then set the desired
Expand All @@ -28,6 +31,11 @@ public class PXLAlbumFilterOptions {
public Boolean hasPermission;
public Boolean hasProduct;
public Boolean inStockOnly;
public ArrayList<Integer> inCategories;
public HashMap<String, Object> filterByUserhandle;
public HashMap<String, Object> computerVision;
public HashMap<String, Object> filterByLocation;
public String filterByRadius;

/***
* Generates the JSON string representing the filter options.
Expand All @@ -42,6 +50,7 @@ public String toParamString() {
jsonFilters.putOpt("starred_photos", starredPhotos);
jsonFilters.putOpt("deleted_photos", deletedPhotos);
jsonFilters.putOpt("flagged_photos", flaggedPhotos);
jsonFilters.putOpt("filter_by_radius", filterByRadius);
//TODO: handle the arrays and dates properly
if (contentSource != null && contentSource.size() > 0) {
JSONArray sources = new JSONArray();
Expand All @@ -68,6 +77,26 @@ public String toParamString() {
jsonFilters.putOpt("has_permission", hasPermission);
jsonFilters.putOpt("has_product", hasProduct);
jsonFilters.putOpt("in_stock_only", inStockOnly);

if (inCategories != null && inCategories.size() > 0) {
JSONArray categoriesJson = new JSONArray(inCategories);
jsonFilters.put("in_categories", categoriesJson);
}

if(filterByUserhandle != null && !filterByUserhandle.isEmpty()){
JSONObject userhandleJson = new JSONObject(filterByUserhandle);
jsonFilters.put("filter_by_userhandle", userhandleJson);
}

if(computerVision != null && !computerVision.isEmpty()){
JSONObject computerVisionJson = new JSONObject(computerVision);
jsonFilters.put("computer_vision", computerVisionJson);
}

if(filterByLocation != null && !filterByLocation.isEmpty()){
JSONObject filterByLocationJson = new JSONObject(filterByLocation);
jsonFilters.put("filter_by_location", filterByLocationJson);
}
} catch (JSONException e) {
e.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ public class PXLAlbumSortOptions {
public String toParamString() {
JSONObject params = new JSONObject();
try {
params.put(sortType.value, true);
params.put(KeyDesc, descending);
if(sortType != PXLAlbumSortType.NONE) {
params.put(sortType.value, true);
params.put(KeyDesc, descending);
}
} catch (JSONException e) {
e.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ public enum PXLAlbumSortType {
PIXLEE_SHARES ("pixlee_shares"),
PIXLEE_LIKES ("pixlee_likes"),
POPULARITY ("popularity"),
PHOTORANK ("photorank");
DYNAMIC ("dynamic"),
NONE ("none");

public final String value;

Expand Down
84 changes: 84 additions & 0 deletions pixleesdk/src/main/java/com/pixlee/pixleesdk/PXLAnalytics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.pixlee.pixleesdk;

import android.content.Context;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;


public class PXLAnalytics {
private static final String TAG = "PXLAnalytics";

protected Context context;


/***
* Constructor requires the context, which will be passed along to the PXLClient
* for volley configuration.
* @param context - context which will be used for volley configuration
*/
public PXLAnalytics(Context context) {
this.context = context;
}

public void addToCart(String sku, String price, Integer quantity, String currency) {
PXLClient pxlClient = PXLClient.getInstance(this.context);
JSONObject body = new JSONObject();

try{
body.put("product_sku", sku);
body.put("price", price);
body.put("quantity", quantity);
if(currency != null){
body.put("currency", currency);
}


} catch (JSONException e) {
e.printStackTrace();
}

pxlClient.makeAnalyticsCall("events/addToCart", body);
}

public void addToCart(String sku, String price, Integer quantity) {
this.addToCart(sku, price, quantity, null);
}


public void conversion(ArrayList<HashMap<String, Object>> cartContents, String cartTotal, Integer cartTotalQuantity, String orderId, String currency){
PXLClient pxlClient = PXLClient.getInstance(this.context);
JSONObject body = new JSONObject();

try{
JSONArray cartContentsJson = new JSONArray(cartContents);
body.put("cart_contents", cartContentsJson);
body.put("cart_total", cartTotal);
body.put("cart_total_quantity", cartTotalQuantity);
if(currency != null){
body.put("currency", currency);
}
if(orderId != null){
body.put("order_id", orderId);
}

} catch (JSONException e) {
e.printStackTrace();
}

pxlClient.makeAnalyticsCall("events/conversion", body);

}
public void conversion(ArrayList<HashMap<String, Object>> cartContents, String cartTotal, Integer cartTotalQuantity, String orderId){
this.conversion(cartContents, cartTotal, cartTotalQuantity, orderId, null);
}
public void conversion(ArrayList<HashMap<String, Object>> cartContents, String cartTotal, Integer cartTotalQuantity) {
this.conversion(cartContents, cartTotal, cartTotalQuantity, null, null);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
public enum PXLAnalyticsEvents {

OPENED_WIDGET ("opened widget"),
OPENED_LIGHTBOX ("opened lightbox");
OPENED_LIGHTBOX ("opened lightbox"),
ADD_TO_CART ("add to cart"),
CONVERSION ("conversion");

public final String value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ public boolean makeAnalyticsCall(final String requestPath, final JSONObject body
StringRequest sr = new StringRequest(Request.Method.POST, finalUrl, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d("ANALYTICS CALL Body", requestBody);
Log.d("ANALYTICS CALL ", response);
}
}, new Response.ErrorListener() {
Expand Down
Loading

0 comments on commit 5b53805

Please sign in to comment.