001/* ****************************************************************************** 002 * Copyright (c) 2002-2011 econda GmbH Karlsruhe 003 * All rights reserved. 004 * <p/> 005 * econda GmbH 006 * Eisenlohrstr. 43 007 * 76135 Karlsruhe 008 * Tel. +49 (721) 663035-35 009 * support@econda.de 010 * <p/> 011 * Redistribution and use in source and binary forms, with or without modification, 012 * are permitted provided that the following conditions are met: 013 * <p/> 014 * * Redistributions of source code must retain the above copyright notice, 015 * this list of conditions and the following disclaimer. 016 * * Redistributions in binary form must reproduce the above copyright notice, 017 * this list of conditions and the following disclaimer in the documentation 018 * and/or other materials provided with the distribution. 019 * * Neither the name of the ECONDA GmbH nor the names of its contributors may 020 * be used to endorse or promote products derived from this software without 021 * specific prior written permission. 022 * <p/> 023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 025 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 026 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 027 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 029 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 030 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 031 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 032 * OF THE POSSIBILITY OF SUCH DAMAGE. 033 *******************************************************************************/ 034package de.econda.droid; 035 036import org.json.JSONArray; 037import org.json.JSONException; 038import org.json.JSONObject; 039 040import de.econda.droid.impl.SimpleDigest; 041 042 043/** 044 * <p>This is the representation of a view.</p> 045 * 046 * <p>After creation of a new PageView, you can add several properties.</p> 047 * 048 * <p>Afterwards you should add the pageView to a Session and perhaps submit the collected data of the session.</p> 049 * 050 * 051 */ 052public class PageView { 053 054 protected final JSONObject properties; 055 056 057 public PageView() { 058 this.properties = new JSONObject(); 059 } 060 061 public PageView(JSONObject properties) { 062 this.properties = properties; 063 } 064 065 /** 066 * Adds a custom String to the properties 067 * 068 * @param key 069 * @param value 070 * @return PageView 071 */ 072 public PageView addProperty(String key, String value) { 073 try { 074 properties.put(key, value); 075 return this; 076 } catch (JSONException e) { 077 throw new RuntimeException(e); 078 } 079 } 080 081 /** 082 * Adds a custom Number to the properties 083 * 084 * @param key 085 * @param value 086 * @return PageView 087 */ 088 public PageView addProperty(String key, Number value) { 089 try { 090 properties.put(key, value); 091 return this; 092 } catch (JSONException e) { 093 throw new RuntimeException(e); 094 } 095 } 096 097 /** 098 * Adds a custom Boolean to the properties 099 * 100 * @param key 101 * @param value 102 * @return PageView 103 */ 104 public PageView addProperty(String key, Boolean value) { 105 try { 106 properties.put(key, value); 107 return this; 108 } catch (JSONException e) { 109 throw new RuntimeException(e); 110 } 111 112 } 113 114 /** 115 * Adds a custom jsonArray to the properties 116 * 117 * @param key 118 * @param jsonArray 119 * @return PageView 120 */ 121 public PageView addProperty(String key, JSONArray jsonArray) { 122 try { 123 properties.put(key, jsonArray); 124 return this; 125 } catch (JSONException e) { 126 throw new RuntimeException(e); 127 } 128 129 } 130 131 /** 132 * Adds a custom jsonObject to the properties 133 * 134 * @param key 135 * @param jsonObject 136 * @return PageView 137 */ 138 public PageView addProperty(String key, JSONObject jsonObject) { 139 try { 140 properties.put(key, jsonObject); 141 return this; 142 } catch (JSONException e) { 143 throw new RuntimeException(e); 144 } 145 } 146 147 148 /** 149 * Adds a contact property 150 * 151 * @param contactType type of the contact-form used 152 * @return PageView 153 */ 154 public PageView addContact(String contactType) { 155 return addProperty("scontact", contactType); 156 } 157 158 /** 159 * Adds a content property 160 * 161 * @param content A content-label for this page 162 * @return PageView 163 */ 164 public PageView addContent(String content) { 165 return addProperty("content", content); 166 } 167 168 /** 169 * 170 * Adds a property for marketing channel ('source').<br> 171 * Default value is 'mobile'.<br> 172 * So your traffic is displayed in chapter 'Mobile' in econda Monitor.<br> 173 * <br> 174 * Please send additional information with the appropriate property.<br> 175 * <br> 176 * For the newsletter channel 'nl' please use property 'newsletter' for submitting additional information<br> 177 * pageView.addMarketingChannel('nl');<br> 178 * pageView.addProperty('newsletter','newsletter name');<br> 179 * <br> 180 * For the keyword channel 'kw' please use property 'adword' for submitting additional information.<br> 181 * pageView.addMarketingChannel('kw');<br> 182 * pageView.addProperty('adword','keyword campaign name');<br> 183 * <br> 184 * For the campaign channel 'cp' and all other channels please use property 'campaign' for submitting additional information.<br> 185 * pageView.addMarketingChannel('cp');<br> 186 * pageView.addProperty('campaign','campaign name');<br> 187 * <br> 188 * MarketingChannel is only stored on first page view of a session.<br> 189 * All subsequent page views in same session inherit the channel of the first page view.<br> 190 * <br> 191 * Marketingchannel 'mobile' is not configured by default in econda Analytics.<br> 192 * Please contact support, if you want to use the mobile channel.<br> 193 * 194 * @param source A marketing channel 195 * @return PageView 196 */ 197 public PageView addMarketingChannel(String source) { 198 return addProperty("source", source); 199 } 200 201 /** 202 * Adds a campaign property 203 * 204 * campaign is only stored on first page view of a session. 205 * All subsequent page views in same session inherit the campaign of the first page view. 206 207 * @param campaign A campaign name 208 * @return PageView 209 */ 210 public PageView addCampaign(String campaign) { 211 return addProperty("campaign", campaign); 212 } 213 214 /** 215 * Adds a download property 216 * 217 * @param label a download-label for this page 218 * @return PageView 219 */ 220 public PageView addDownload(String label) { 221 return addProperty("download", label); 222 } 223 224 225 /** 226 * Adds a billing property 227 * 228 * @param billId unique identifier for this bill 229 * @param customerId unique identifier for this customer 230 * @param total the total sum of this bill! 231 * @param country the country of the customer 232 * @param cip the cip of the customer 233 * @param city the city of the customer 234 * @return PageView 235 */ 236 public PageView addBill(String billId, 237 String customerId, Double total, String country, 238 String cip, String city) { 239 240 JSONArray lineValues = new JSONArray(); 241 242 lineValues.put(billId); 243 lineValues.put(customerId); 244 lineValues.put(getBillLocationString(country, cip, city)); 245 lineValues.put(total); 246 return addProperty("billing", lineValues); 247 } 248 249 250 private static String getBillLocationString(String country, String cip, String city) { 251 StringBuilder location = new StringBuilder(); 252 253 if (country != null) { 254 location.append(country); 255 location.append("/"); 256 } 257 258 if ((cip != null) && (cip.length() > 2)) { 259 location.append(cip.charAt(0)); 260 location.append("/"); 261 location.append(cip.substring(0, 2)); 262 location.append("/"); 263 } 264 265 if (city != null) { 266 location.append(city); 267 location.append("/"); 268 } 269 270 if (cip != null) { 271 location.append(cip); 272 } 273 274 if (location.length() == 0) { 275 return "NULL"; 276 } 277 278 return location.toString(); 279 } 280 281 282 /** 283 * Adds a login property.<br> 284 * 285 * This method always scramble the userId with a MD5 Hash for you. 286 * This is perhaps necessary to fulfill the German "Datenschutzgesetz". 287 * 288 * @param userId UserID or email - must be a unique identifier 289 * @param resultCode 0 if success, positive int for error numbers 290 * 291 * @return PageView 292 */ 293 public PageView addLogin(String userId, int resultCode) { 294 return addLogin(userId, resultCode, true); 295 } 296 297 298 /** 299 * Adds a login property.<br> 300 * 301 * Set Parameter scramble to true, if you want that this library is hashing the userId for you. 302 * This is perhaps necessary to fulfill the German "Datenschutzgesetz". 303 * 304 * @param userId UserID or email - must be a unique identifier 305 * @param resultCode 0 if success, positive int for error numbers 306 * @param scramble whether to use hashed userId or plain userId 307 * 308 * @return PageView 309 */ 310 public PageView addLogin(String userId, int resultCode, boolean scramble) { 311 if (scramble){ 312 userId = SimpleDigest.digest(userId); 313 } 314 315 JSONArray array = new JSONArray(); 316 array.put(userId); 317 array.put(resultCode); 318 return addProperty("login", array); 319 } 320 321 322 /** 323 * Adds a target property.<br><br> 324 * 325 * @param target Name for this Target, e.g. download, lottery 326 * @param additionalInfo additional Information, e.g. the Name of the downloaded Document 327 * @param score Your value of this target (used for calculation of conversationrate) 328 * @param rule Method to use. Only first of session, all or usage of default value configured in econda-monitor 329 * @return PageView 330 */ 331 public PageView addTarget(String target, String additionalInfo, double score, TargetRule rule) { 332 try { 333 JSONArray array = new JSONArray(); 334 array.put(target); 335 array.put(additionalInfo); 336 array.put(score); 337 array.put(rule.transmitKey); 338 return addProperty("Target", array); 339 } catch (JSONException e) { 340 throw new RuntimeException(e); 341 } 342 } 343 344 345 /** 346 * Adds a orderProcess property.<br><br> 347 * 348 * @param processStep A Label to identify the step in the order-process by 349 * convention this is a positive int followed by an underscore and 350 * the label e.g. "1_Kundendaten", "2_Zahlungsoptionen", .. 351 * @return PageView 352 */ 353 public PageView addOrderProcess(String processStep) { 354 return addProperty("orderProcess", processStep); 355 } 356 357 358 /** 359 * Adds a register property.<br> 360 * 361 * This method always scramble the userId with a MD5 Hash for you. 362 * This is perhaps necessary to fulfill the German "Datenschutzgesetz". 363 * 364 * @param userId UserID or email - must be a unique identifier 365 * @param resultCode 0 if success, positive int for error numbers 366 * 367 * @return PageView 368 */ 369 public PageView addRegister(String userId, int resultCode) { 370 return addRegister(userId, resultCode, true); 371 } 372 373 374 /** 375 * Adds a register property.<br> 376 * 377 * Set Parameter scramble to true, if you want that this library is hashing the userId for you. 378 * This is perhaps necessary to fulfill the German "Datenschutzgesetz". 379 * 380 * @param userId UserID or email - must be a unique identifier 381 * @param resultCode 0 if success, positive int for error numbers 382 * @param scramble whether to hash userId or use given userId 383 * 384 * @return PageView 385 */ 386 public PageView addRegister(String userId, int resultCode, boolean scramble) { 387 if (scramble){ 388 userId = SimpleDigest.digest(userId); 389 } 390 391 JSONArray array = new JSONArray(); 392 array.put(userId); 393 array.put(resultCode); 394 return addProperty("register", array); 395 } 396 397 398 /** 399 * Adds a search property 400 * 401 * @param queryString the search string 402 * @param numberOfHits the number of hits found 403 * @return PageView 404 */ 405 public PageView addSearch(String queryString, int numberOfHits) { 406 JSONArray array = new JSONArray(); 407 array.put(queryString); 408 array.put(numberOfHits); 409 return addProperty("search", array); 410 } 411 412 /** 413 * Adds a siteid property. Some shop systems can 414 * handle multiple sites. If we have to distinguish them, we set the 415 * siteid for the actual shop. 416 * 417 * @param siteId unique identifier for this site 418 * @return PageView 419 */ 420 public PageView addSiteId(String siteId) { 421 return addProperty("siteid", siteId); 422 } 423 424 /** 425 * Adds a intern property. 426 * 427 * @param intern 428 * @return PageView 429 */ 430 public PageView addIntern(String intern) { 431 return addProperty("intern", intern); 432 } 433 434 /** 435 * Adds a marker property. 436 * 437 * @param marker 438 * @return PageView 439 */ 440 public PageView addMarker(String marker) { 441 return addProperty("marker", marker); 442 } 443 444 /** 445 * Adds a country property. Some shop systems can 446 * handle multiple sites. If we have to distinguish them, we set the 447 * countryId for the actual shop. 448 * 449 * @param countryId unique identifier for this country 450 * @return PageView 451 */ 452 public PageView addCountryId(String countryId) { 453 return addProperty("countryid", countryId); 454 } 455 456 /** 457 * Adds a language property. Some shop systems can 458 * handle multiple languages. If we have to distinguish them, we set the 459 * language. 460 * 461 * @param langId unique identifier for this language 462 * @return PageView 463 */ 464 public PageView addLangId(String langId) { 465 return addProperty("langid", langId); 466 } 467 468 /** 469 * adds a addToBasket - Event to this page 470 * 471 * @param item the BasketItem this Event belongs to 472 * @return PageView 473 */ 474 public PageView addProductAddToBasket(BasketItem item) { 475 return addProductCustomEvent(item, "c_add"); 476 } 477 478 /** 479 * adds a removeFromBasket - Event to this page 480 * 481 * @param item the BasketItem this Event belongs to 482 * @return PageView 483 */ 484 public PageView addProductRemoveFromBasket(BasketItem item) { 485 return addProductCustomEvent(item, "c_rmv"); 486 } 487 488 489 /** 490 * Adds a ec_Event property. 491 * Stored as array of array. 492 * Array contains the eventType = 'buy' and all BasketItem-Informations. 493 * 494 * @param item BasketItem 495 * @return PageView 496 */ 497 public PageView addProductBuy(BasketItem item) { 498 return addProductCustomEvent(item, "buy"); 499 } 500 501 /** 502 * Adds a ec_Event property. 503 * Stored as array of array. 504 * Array contains the eventType = 'view' and all BasketItem-Informations. 505 * 506 * @param item BasketItem this detail View belongs to 507 * @return PageView 508 */ 509 public PageView addProductView(BasketItem item) { 510 return addProductCustomEvent(item, "view"); 511 } 512 513 514 /** 515 * Adds a ec_Event property with custom eventType. 516 * Stored as array of array. 517 * Array contains the custom eventType and all BasketItem-Informations. 518 * 519 * @param item the item the EC-Event belongs to 520 * @param eventType type of the event like c_add, c_rmv, view, buy 521 * @return PageView 522 */ 523 public PageView addProductCustomEvent(BasketItem item, String eventType) { 524 try { 525 526 JSONObject obj = new JSONObject(); 527 528 obj.put("type", eventType); 529 item.appendBasketItemProperties(obj); 530 531 JSONArray outerArray = properties.optJSONArray("ec_Event"); 532 if (outerArray == null) { 533 outerArray = new JSONArray(); 534 properties.put("ec_Event", outerArray); 535 } 536 537 outerArray.put(obj); 538 return this; 539 } catch (JSONException e) { 540 throw new RuntimeException(e); 541 } 542 543 } 544 545 JSONObject getProperties() { 546 return properties; 547 } 548}