Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support adding items with custom attributes. #45

Merged
merged 11 commits into from
Dec 12, 2023
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ Clickstream Android SDK can help you easily collect and report in-app events fro

The SDK relies on the Amplify for Android SDK Core Library and is developed according to the Amplify Android SDK plug-in specification. In addition, we've added features that automatically collect common user events and attributes (e.g., screen view, first open) to simplify data collection for users.

Visit our [Documentation site](https://awslabs.github.io/clickstream-analytics-on-aws/en/sdk-manual/android/) to learn more about Clickstream Android SDK.
zhu-xiaowei marked this conversation as resolved.
Show resolved Hide resolved

### Platform Support

The Clickstream SDK supports Android API level 16 (Android 4.1) and above.
Clickstream Android SDK supports Android 4.1 (API level 16) and later.

## Integrate SDK

Expand Down Expand Up @@ -173,6 +175,32 @@ ClickstreamAnalytics.addUserAttributes(clickstreamUserAttribute);

Current login user‘s attributes will be cached in disk, so the next time app launch you don't need to set all user's attribute again, of course you can update the current user's attribute when it changes.

#### Record event with items

You can add the following code to log an event with an item.

```java
import software.aws.solution.clickstream.ClickstreamAnalytcs;
import software.aws.solution.clickstream.ClickstreamItem;

ClickstreamItem item_book = ClickstreamItem.builder()
.add(ClickstreamAnalytics.Item.ITEM_ID, "123")
.add(ClickstreamAnalytics.Item.ITEM_NAME, "'Nature'")
.add(ClickstreamAnalytics.Item.ITEM_CATEGORY, "book")
.add(ClickstreamAnalytics.Item.PRICE, 99)
.build();

ClickstreamEvent event = ClickstreamEvent.builder()
.name("view_item")
.add(ClickstreamAnalytics.Item.ITEM_ID, "123")
.add(ClickstreamAnalytics.Item.CURRENCY, "USD")
.add("event_category", "recommended")
.setItems(new ClickstreamItem[] {item_book})
.build();

ClickstreamAnalytics.recordEvent(event);
```

#### Log the event json in debug mode

```java
Expand All @@ -195,7 +223,7 @@ ClickstreamAnalytics.getClickStreamConfiguration()
.withCustomDns(CustomOkhttpDns.getInstance());
```

If you want to use custom DNS for network request, you can create your `CustomOkhttpDns` which implementaion `okhttp3.Dns`, then config `.withCustomDns(CustomOkhttpDns.getInstance())` to make it works.
If you want to use custom DNS for network request, you can create your `CustomOkhttpDns` which implementation `okhttp3.Dns`, then config `.withCustomDns(CustomOkhttpDns.getInstance())` to make it works.

#### Send event immediately

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,18 @@ public void recordEvent(@NonNull String eventName) {

@Override
public void recordEvent(@NonNull AnalyticsEventBehavior analyticsEvent) {
ClickstreamEvent event = (ClickstreamEvent) analyticsEvent;
final AnalyticsEvent clickstreamEvent =
analyticsClient.createEvent(analyticsEvent.getName());
analyticsClient.createEvent(event.getName());

if (clickstreamEvent != null && analyticsEvent.getProperties() != null) {
for (Map.Entry<String, AnalyticsPropertyBehavior<?>> entry : analyticsEvent.getProperties()) {
AnalyticsPropertyBehavior<?> property = entry.getValue();
clickstreamEvent.addAttribute(entry.getKey(), property.getValue());
if (clickstreamEvent != null) {
if (analyticsEvent.getProperties() != null) {
for (Map.Entry<String, AnalyticsPropertyBehavior<?>> entry : analyticsEvent.getProperties()) {
AnalyticsPropertyBehavior<?> property = entry.getValue();
clickstreamEvent.addAttribute(entry.getKey(), property.getValue());
}
}
clickstreamEvent.addItems(event.getItems());
analyticsClient.recordEvent(clickstreamEvent);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,66 @@ public static ClickstreamConfiguration getClickStreamConfiguration() {
assert client != null;
return client.getClickstreamConfiguration();
}

/**
* Item attributes.
*/
public static class Item {
/**
* key to item id.
*/
public static final String ITEM_ID = "id";
/**
* key to item name.
*/
public static final String ITEM_NAME = "name";
/**
* key to item location id.
*/
public static final String LOCATION_ID = "location_id";
/**
* key to item brand.
*/
public static final String ITEM_BRAND = "brand";
/**
* key to item currency.
*/
public static final String CURRENCY = "currency";
/**
* key to item price.
*/
public static final String PRICE = "price";
/**
* key to item quantity.
*/
public static final String QUANTITY = "quantity";
/**
* key to item creative name.
*/
public static final String CREATIVE_NAME = "creative_name";
/**
* key to item creative slot.
*/
public static final String CREATIVE_SLOT = "creative_slot";
/**
* key to item category.
*/
public static final String ITEM_CATEGORY = "item_category";
/**
* key to item category2.
*/
public static final String ITEM_CATEGORY2 = "item_category2";
/**
* key to item category3.
*/
public static final String ITEM_CATEGORY3 = "item_category3";
/**
* key to item category4.
*/
public static final String ITEM_CATEGORY4 = "item_category4";
/**
* key to item category5.
*/
public static final String ITEM_CATEGORY5 = "item_category5";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,12 @@ public final class ClickstreamEvent implements AnalyticsEventBehavior {
private static final int MAX_VALUE_LENGTH = 1024;
private final String name;
private final AnalyticsProperties properties;
private final ClickstreamItem[] items;

private ClickstreamEvent(String name, AnalyticsProperties properties) {
private ClickstreamEvent(String name, AnalyticsProperties properties, ClickstreamItem[] items) {
this.name = name;
this.properties = properties;
this.items = items;
}

/**
Expand All @@ -72,6 +74,16 @@ public AnalyticsProperties getProperties() {
return properties;
}

/**
* Returns the {@link ClickstreamItem} array of the event.
*
* @return The {@link ClickstreamItem} array of the event
*/
@NonNull
public ClickstreamItem[] getItems() {
return items;
}

/**
* Returns a new {@link Builder} to configure an instance of ClickstreamEvent.
*
Expand All @@ -91,7 +103,8 @@ public static Builder builder() {
*/
public static final class Builder {
private String name;
private AnalyticsProperties.Builder propertiesBuilder;
private final AnalyticsProperties.Builder propertiesBuilder;
private ClickstreamItem[] items;

/**
* the builder for add event attribute.
Expand Down Expand Up @@ -181,6 +194,18 @@ public Builder add(@NonNull @Size(min = 1L, max = MAX_NAME_LENGTH) String name,
return this;
}

/**
* Adds items to the {@link ClickstreamEvent}.
*
* @param items The items of the event
* @return Current Builder instance, for fluent method chaining
*/
@NonNull
public Builder setItems(ClickstreamItem[] items) {
this.items = items;
return this;
}

/**
* Returns the built {@link ClickstreamEvent}.
*
Expand All @@ -189,7 +214,7 @@ public Builder add(@NonNull @Size(min = 1L, max = MAX_NAME_LENGTH) String name,
*/
@NonNull
public ClickstreamEvent build() {
return new ClickstreamEvent(name, propertiesBuilder.build());
return new ClickstreamEvent(name, propertiesBuilder.build(), this.items);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.aws.solution.clickstream;

import androidx.annotation.NonNull;
import androidx.annotation.Size;

import com.amazonaws.logging.Log;
import com.amazonaws.logging.LogFactory;
import org.json.JSONException;
import org.json.JSONObject;
import software.aws.solution.clickstream.client.Event;

/**
* ClickstreamItem for item record.
*/
public final class ClickstreamItem {
private static final Log LOG = LogFactory.getLog(ClickstreamItem.class);
private final JSONObject attributes;

/**
* Constructor for init the ClickstreamItem.
*
* @param attributes An instance of the builder with the desired attributes set.
*/
private ClickstreamItem(@NonNull JSONObject attributes) {
this.attributes = attributes;
}

/**
* the getter for attributes.
*
* @return the attributes json object.
*/
public JSONObject getAttributes() {
return attributes;
}


/**
* Begins construction of an {@link ClickstreamItem} using a builder pattern.
*
* @return An {@link ClickstreamItem.Builder} instance
*/
@NonNull
public static Builder builder() {
return new ClickstreamItem.Builder();
}

/**
* Builder for the {@link ClickstreamItem} class.
*/
public static class Builder {
private final JSONObject builder = new JSONObject();

/**
* constructor for Builder.
*
* @param key A name for the property
* @param value A String to store in the property
* @return Current Builder instance, for fluent method chaining
*/
@NonNull
public ClickstreamItem.Builder add(@NonNull @Size(min = 1L, max = Event.Limit.MAX_LENGTH_OF_NAME) String key,
@NonNull @Size(min = 0L, max = Event.Limit.MAX_LENGTH_OF_ITEM_VALUE)
String value) {
setAttribute(key, value);
return this;
}

/**
* Adds double value.
*
* @param key A name for the property
* @param value A Double to store in the property
* @return Current Builder instance, for fluent method chaining
*/
@NonNull
public ClickstreamItem.Builder add(@NonNull @Size(min = 1L, max = Event.Limit.MAX_LENGTH_OF_NAME) String key,
@NonNull Double value) {
setAttribute(key, value);
return this;
}

/**
* Adds boolean value.
*
* @param key A name for the property
* @param value A Boolean to store in the property
* @return Current Builder instance, for fluent method chaining
*/
@NonNull
public ClickstreamItem.Builder add(@NonNull @Size(min = 1L, max = Event.Limit.MAX_LENGTH_OF_NAME) String key,
@NonNull Boolean value) {
setAttribute(key, value);
return this;
}

/**
* Adds int value.
*
* @param key A name for the property
* @param value An Integer to store in the property
* @return Current Builder instance, for fluent method chaining
*/
@NonNull
public ClickstreamItem.Builder add(@NonNull @Size(min = 1L, max = Event.Limit.MAX_LENGTH_OF_NAME) String key,
@NonNull Integer value) {
setAttribute(key, value);
return this;
}

/**
* Adds long value.
*
* @param key A name for the property
* @param value An Long to store in the property
* @return Current Builder instance, for fluent method chaining
*/
@NonNull
public ClickstreamItem.Builder add(@NonNull @Size(min = 1L, max = Event.Limit.MAX_LENGTH_OF_NAME) String key,
@NonNull Long value) {
setAttribute(key, value);
return this;
}

private void setAttribute(String key, Object value) {
try {
builder.putOpt(key, value);
} catch (JSONException exception) {
LOG.warn("error parsing json, error message:" + exception.getMessage());
}
}

/**
* Builds an instance of {@link ClickstreamItem}, using the provided values.
*
* @return An {@link ClickstreamItem}
*/
@NonNull
public ClickstreamItem build() {
return new ClickstreamItem(builder);
}
}
}
Loading
Loading