Skip to content

Commit 42e0b23

Browse files
authored
Support Get user interaction statistics. Close #378 (#477)
1 parent 0ce0414 commit 42e0b23

File tree

8 files changed

+447
-1
lines changed

8 files changed

+447
-1
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2020 LINE Corporation
3+
*
4+
* LINE Corporation licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package com.linecorp.bot.client;
18+
19+
import java.io.IOException;
20+
import java.util.Collections;
21+
22+
import org.junit.Before;
23+
import org.junit.Test;
24+
25+
import com.linecorp.bot.model.Narrowcast;
26+
import com.linecorp.bot.model.message.TextMessage;
27+
import com.linecorp.bot.model.narrowcast.Filter;
28+
import com.linecorp.bot.model.narrowcast.filter.GenderDemographicFilter;
29+
import com.linecorp.bot.model.narrowcast.filter.GenderDemographicFilter.Gender;
30+
import com.linecorp.bot.model.response.BotApiResponse;
31+
import com.linecorp.bot.model.response.GetMessageEventResponse;
32+
import com.linecorp.bot.model.response.NarrowcastProgressResponse;
33+
import com.linecorp.bot.model.response.NarrowcastProgressResponse.Phase;
34+
35+
import lombok.extern.slf4j.Slf4j;
36+
37+
@Slf4j
38+
public class InsightIntegrationTest {
39+
private LineMessagingClient target;
40+
41+
@Before
42+
public void setUp() throws IOException {
43+
IntegrationTestSettings settings = IntegrationTestSettingsLoader.load();
44+
target = LineMessagingClientFactory.create(settings);
45+
}
46+
47+
@Test
48+
public void testGetMessageEvent() throws Exception {
49+
// Send narrowcast message.
50+
BotApiResponse response = target.narrowcast(
51+
new Narrowcast(new TextMessage("Narrowcast test(gender=male)"),
52+
Filter.builder()
53+
.demographic(
54+
GenderDemographicFilter
55+
.builder()
56+
.oneOf(Collections.singletonList(Gender.MALE))
57+
.build()
58+
).build())).get();
59+
log.info("Narrowcast response={}", response);
60+
61+
// Waiting sending process
62+
for (int i = 0; i < 10; i++) {
63+
NarrowcastProgressResponse progressResponse = target.getNarrowcastProgress(
64+
response.getRequestId()).get();
65+
log.info("Progress={}", progressResponse);
66+
log.info("Progress response={}", progressResponse);
67+
if (progressResponse.getPhase() == Phase.SUCCEEDED
68+
|| progressResponse.getPhase() == Phase.FAILED) {
69+
break;
70+
}
71+
Thread.sleep(1000);
72+
}
73+
74+
GetMessageEventResponse messageEvent = target.getMessageEvent(
75+
response.getRequestId()).get();
76+
log.info("messageEvent={}", messageEvent);
77+
}
78+
}

line-bot-api-client/src/integrationTest/java/com/linecorp/bot/client/IntegrationTestSettingsLoader.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public class IntegrationTestSettingsLoader {
3131
public static IntegrationTestSettings load() throws IOException {
3232
// Do not run all test cases in this class when src/test/resources/integration_test_settings.yml doesn't
3333
// exist.
34-
Assume.assumeTrue(TEST_RESOURCE != null);
34+
Assume.assumeTrue("exists integration_test_settings.yml in resource directory",
35+
TEST_RESOURCE != null);
3536

3637
return new ObjectMapper(new YAMLFactory())
3738
.registerModule(new ParameterNamesModule())

line-bot-api-client/src/main/java/com/linecorp/bot/client/LineMessagingClient.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.linecorp.bot.model.profile.MembersIdsResponse;
3030
import com.linecorp.bot.model.profile.UserProfileResponse;
3131
import com.linecorp.bot.model.response.BotApiResponse;
32+
import com.linecorp.bot.model.response.GetMessageEventResponse;
3233
import com.linecorp.bot.model.response.GetNumberOfFollowersResponse;
3334
import com.linecorp.bot.model.response.GetNumberOfMessageDeliveriesResponse;
3435
import com.linecorp.bot.model.response.IssueLinkTokenResponse;
@@ -356,6 +357,16 @@ CompletableFuture<BotApiResponse> setRichMenuImage(
356357
*/
357358
CompletableFuture<GetNumberOfFollowersResponse> getNumberOfFollowers(String date);
358359

360+
/**
361+
* Returns statistics about how users interact with narrowcast messages or broadcast messages sent from your
362+
* LINE Official Account.
363+
*
364+
* <p>You can get statistics per message or per bubble.</p>
365+
* @param requestId Request ID of a narrowcast message or broadcast message. Each Messaging API request has
366+
* a request ID. Find it in the response headers.
367+
*/
368+
CompletableFuture<GetMessageEventResponse> getMessageEvent(String requestId);
369+
359370
/**
360371
* Retrieves the demographic attributes for a bot's friends.
361372
*

line-bot-api-client/src/main/java/com/linecorp/bot/client/LineMessagingClientImpl.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.linecorp.bot.model.profile.MembersIdsResponse;
3131
import com.linecorp.bot.model.profile.UserProfileResponse;
3232
import com.linecorp.bot.model.response.BotApiResponse;
33+
import com.linecorp.bot.model.response.GetMessageEventResponse;
3334
import com.linecorp.bot.model.response.GetNumberOfFollowersResponse;
3435
import com.linecorp.bot.model.response.GetNumberOfMessageDeliveriesResponse;
3536
import com.linecorp.bot.model.response.IssueLinkTokenResponse;
@@ -275,6 +276,11 @@ public CompletableFuture<GetNumberOfFollowersResponse> getNumberOfFollowers(Stri
275276
return toFuture(retrofitImpl.getNumberOfFollowers(date));
276277
}
277278

279+
@Override
280+
public CompletableFuture<GetMessageEventResponse> getMessageEvent(String requestId) {
281+
return toFuture(retrofitImpl.getMessageEvent(requestId));
282+
}
283+
278284
// TODO: Extract this method.
279285
static <T> CompletableFuture<T> toFuture(Call<T> callToWrap) {
280286
final CallbackAdaptor<T> completableFuture = new CallbackAdaptor<>();

line-bot-api-client/src/main/java/com/linecorp/bot/client/LineMessagingService.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.linecorp.bot.model.ReplyMessage;
2626
import com.linecorp.bot.model.profile.MembersIdsResponse;
2727
import com.linecorp.bot.model.profile.UserProfileResponse;
28+
import com.linecorp.bot.model.response.GetMessageEventResponse;
2829
import com.linecorp.bot.model.response.GetNumberOfFollowersResponse;
2930
import com.linecorp.bot.model.response.GetNumberOfMessageDeliveriesResponse;
3031
import com.linecorp.bot.model.response.IssueLinkTokenResponse;
@@ -337,4 +338,15 @@ Call<Void> linkRichMenuToUser(
337338
*/
338339
@GET("v2/bot/insight/followers")
339340
Call<GetNumberOfFollowersResponse> getNumberOfFollowers(@Query("date") String date);
341+
342+
/**
343+
* Returns statistics about how users interact with narrowcast messages or broadcast messages sent from your
344+
* LINE Official Account.
345+
*
346+
* <p>You can get statistics per message or per bubble.</p>
347+
* @param requestId Request ID of a narrowcast message or broadcast message. Each Messaging API request has
348+
* a request ID. Find it in the response headers.
349+
*/
350+
@GET("v2/bot/insight/message/event")
351+
Call<GetMessageEventResponse> getMessageEvent(@Query("requestId") String requestId);
340352
}
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* Copyright 2020 LINE Corporation
3+
*
4+
* LINE Corporation licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*
16+
*/
17+
18+
package com.linecorp.bot.model.response;
19+
20+
import java.util.List;
21+
22+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
23+
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
24+
25+
import lombok.Builder;
26+
import lombok.Value;
27+
28+
/**
29+
* Response of the getting user interaction statistics API.
30+
*/
31+
@Value
32+
@Builder
33+
@JsonDeserialize(builder = GetMessageEventResponse.GetMessageEventResponseBuilder.class)
34+
public class GetMessageEventResponse {
35+
Overview overview;
36+
List<Message> messages;
37+
List<Click> clicks;
38+
39+
/**
40+
* Summary of message statistics.
41+
*/
42+
@Value
43+
@Builder
44+
@JsonDeserialize(builder = Overview.OverviewBuilder.class)
45+
public static class Overview {
46+
/**
47+
* Request ID.
48+
*/
49+
String requestId;
50+
51+
/**
52+
* UNIX timestamp for message delivery time.
53+
*/
54+
Long timestamp;
55+
56+
/**
57+
* Number of messages delivered. This property shows values of less than 20. However, if all messages
58+
* have not been sent, it will be null.
59+
*/
60+
Long delivered;
61+
62+
/**
63+
* Number of people who opened the message, meaning they displayed at least 1 bubble.
64+
*/
65+
Long uniqueImpression;
66+
67+
/**
68+
* Number of people who opened any URL in the message.
69+
*/
70+
Long uniqueClick;
71+
72+
/**
73+
* Number of people who started playing any video or audio in the message.
74+
*/
75+
Long uniqueMediaPlayed;
76+
77+
/**
78+
* Number of people who played the entirety of any video or audio in the message.
79+
*/
80+
Long uniqueMediaPlayed100Percent;
81+
82+
@JsonPOJOBuilder(withPrefix = "")
83+
public static class OverviewBuilder {
84+
// Filled by lombok
85+
}
86+
}
87+
88+
@Value
89+
@Builder
90+
@JsonDeserialize(builder = Message.MessageBuilder.class)
91+
public static class Message {
92+
/**
93+
* Bubble's serial number.
94+
*/
95+
Long seq;
96+
97+
/**
98+
* Number of times the bubble was displayed.
99+
*/
100+
Long impression;
101+
102+
/**
103+
* Number of times audio or video in the bubble started playing.
104+
*/
105+
Long mediaPlayed;
106+
107+
/**
108+
* Number of times audio or video in the bubble was played from start to 25%.
109+
*/
110+
Long mediaPlayed25Percent;
111+
112+
/**
113+
* Number of times audio or video in the bubble was played from start to 50%.
114+
*/
115+
Long mediaPlayed50Percent;
116+
117+
/**
118+
* Number of times audio or video in the bubble was played from start to 75%.
119+
*/
120+
Long mediaPlayed75Percent;
121+
122+
/**
123+
* Number of times audio or video in the bubble was played in its entirety.
124+
*/
125+
Long mediaPlayed100Percent;
126+
127+
/**
128+
* Number of people that started playing audio or video in the bubble.
129+
*/
130+
Long uniqueMediaPlayed;
131+
132+
/**
133+
* Number of people that played audio or video in the bubble from start to 25%.
134+
*/
135+
Long uniqueMediaPlayed25Percent;
136+
137+
/**
138+
* Number of people that played audio or video in the bubble from start to 50%.
139+
*/
140+
Long uniqueMediaPlayed50Percent;
141+
142+
/**
143+
* Number of people that played audio or video in the bubble from start to 75%.
144+
*/
145+
Long uniqueMediaPlayed75Percent;
146+
147+
/**
148+
* Number of people that played audio or video in the bubble in its entirety.
149+
*/
150+
Long uniqueMediaPlayed100Percent;
151+
152+
@JsonPOJOBuilder(withPrefix = "")
153+
public static class MessageBuilder {
154+
// Filled by lombok
155+
}
156+
}
157+
158+
/**
159+
* Array of information about opened URLs in the message.
160+
*/
161+
@Value
162+
@Builder
163+
@JsonDeserialize(builder = Click.ClickBuilder.class)
164+
public static class Click {
165+
/**
166+
* The URL's serial number.
167+
*/
168+
Long seq;
169+
170+
/**
171+
* URL.
172+
*/
173+
String url;
174+
175+
/**
176+
* Number of times the URL was opened.
177+
*/
178+
Long click;
179+
180+
/**
181+
* Number of people that opened the URL.
182+
*/
183+
Long uniqueClick;
184+
185+
/**
186+
* Number of people who opened this url through any link in the message. If a message contains two
187+
* links to the same URL and a user opens both links, they're counted only once.
188+
*/
189+
Long uniqueClickOfRequest;
190+
191+
@JsonPOJOBuilder(withPrefix = "")
192+
public static class ClickBuilder {
193+
// Filled by lombok
194+
}
195+
}
196+
197+
@JsonPOJOBuilder(withPrefix = "")
198+
public static class GetMessageEventResponseBuilder {
199+
// Filled by lombok
200+
}
201+
}

0 commit comments

Comments
 (0)