{"cells":[{"metadata":{"_uuid":"5ed3f2347f5ad29150aaad1fd10a759df3e174db"},"cell_type":"markdown","source":"# Introduction\n\nKaggle describes this competition as follows:\n>In this competition, you’re challenged to analyze a Google Merchandise Store (also known as GStore, where Google swag is sold) customer dataset to predict revenue per customer. Hopefully, the outcome will be more actionable operational changes and a better use of marketing budgets for those companies who choose to use data analysis on top of GA data. For each fullVisitorId in the test set, you must predict the natural log of their total revenue. Submissions are scored on the root mean squared error (RMSE).\n\nThis kernel contains an **EDA**, a **Baseline LightGBM model**, and also **Screenshots of the app**. Since I am familiar with Google Analytics and also have the Google Mechandising store setup as a property in my personal environment, I though it would be good to start with some screen shots of the actual application. In the comments, the question was raised \"how I did this\". Well, actually this is pretty easy to setup, and you can find out how to do that through this link: [Learn by experimenting with data from the Google Merchandise Store.](https://support.google.com/analytics/answer/6367342?hl=en). However, once I really got started with the EDA, I increasingly found the large screenshots to become a bit distracting and I decided to separate these from the EDA and move them to an Appendix. To go straight to the screenshots: [Appendix: Screenshots](#Appendix:-Screenshots-of-the-app).\n\n# Table of contents\n\n* [1. Loading libraries and data](#1.-Loading-libraries-and-data)\n\n* [2. EDA](#2.-EDA)\n\n  * [2.1 Missing data](#2.1-Missing-data)\n  * [2.2 The response variable; transactionRevenue](#2.2-The-response-variable;-transactionRevenue)\n  * [2.3 Time series and grouping by workday and by month](#2.3-Time-series-and-grouping-by-workday-and-by-month)\n   * [2.3.1 Time series of sessions and revenues by Date](#2.3.1-Time-series-of-sessions-and-revenues-by-Date)\n   * [2.3.2 Sessions and revenues by Workday](#2.3.2-Sessions-and-revenues-by-Workday)\n   * [2.3.3 Sessions and revenues by Month](#2.3.3-Sessions-and-revenues-by-Month)\n  * [2.4 Channel grouping and the source/medium dimension](#2.4-Channel-grouping-and-the-source/medium-dimension)\n   * [2.4.1 Channel grouping](#2.4.1-Channel-grouping)\n   * [2.4.2 The source/medium dimension](#2.4.2-The-source/medium-dimension)\n  * [2.5 Operating system, browser and device category](#2.5-Operating-system,-browser-and-device-category)\n   * [2.5.1 Device category](#2.5.1-Device-category)\n   * [2.5.2 Operating system](#2.5.2-Operating-System)\n   * [2.5.3 Browser](#2.5.3-Browser)\n  * [2.6 Pageviews, Bounces and Hits](#2.6-Pageviews,-Bounces-and-Hits)\n   * [2.6.1 Pageviews; all sessions.](#2.6.1-Pageviews;-all-sessions.)\n   * [2.6.2 Pageviews; only sessions with any transaction revenue.](#2.6.2-Pageviews;-only-sessions-with-any-transaction-revenue.)\n   * [2.6.3 Pageviews versus percent transactions](#2.6.3-Pageviews-versus-percent-transactions)\n   * [2.6.4 Bounces](#2.6.4-Bounces)\n   * [2.6.5 Hits](#2.6.5-Hits)\n  * [2.7 Sessions, revenues and transactions by country](#2.7-Sessions,-revenues-and-transactions-by-country)\n* [3. LightGBM Model](#3.-LightGBM-Model)\n  \n* [Appendix: Screenshots of the app](#Appendix:-Screenshots-of-the-app)"},{"metadata":{"_uuid":"6cbaabff2b986581364613c02be3032e9e92092f"},"cell_type":"markdown","source":"# 1. Loading libraries and data"},{"metadata":{"_uuid":"7a5ee19ec2b5eb356cebd6ed035a79b275926051","_execution_state":"idle","trusted":true,"_kg_hide-output":true},"cell_type":"code","source":"library(tidyverse)\nlibrary(jsonlite)\nlibrary(scales)\nlibrary(lubridate)\nlibrary(repr)\nlibrary(ggrepel)\nlibrary(gridExtra)\nlibrary(lightgbm)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"80d5809c980a2ab652c6386cb9a22fd286bb32a6","_kg_hide-output":true},"cell_type":"code","source":"train <- read_csv(\"../input/train.csv\")\ntest <- read_csv(\"../input/test.csv\")","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"add2073af288f9fe4c6c754d0cba9fe96c1757c5"},"cell_type":"markdown","source":"I am using ML's script to convert the JSON columns in the train and test sets into tidy variables to make a quick start, Thanks ML (and I upvoted your kernel of course)!"},{"metadata":{"trusted":true,"_uuid":"ac9ecd30fd2c611c7d871fb40049ecd7e6c71363","_kg_hide-input":true},"cell_type":"code","source":"#JSON columns are \"device\", \"geoNetwork\", \"totals\", \"trafficSource\"\n\ntr_device <- paste(\"[\", paste(train$device, collapse = \",\"), \"]\") %>% fromJSON(flatten = T)\ntr_geoNetwork <- paste(\"[\", paste(train$geoNetwork, collapse = \",\"), \"]\") %>% fromJSON(flatten = T)\ntr_totals <- paste(\"[\", paste(train$totals, collapse = \",\"), \"]\") %>% fromJSON(flatten = T)\ntr_trafficSource <- paste(\"[\", paste(train$trafficSource, collapse = \",\"), \"]\") %>% fromJSON(flatten = T)\n\nte_device <- paste(\"[\", paste(test$device, collapse = \",\"), \"]\") %>% fromJSON(flatten = T)\nte_geoNetwork <- paste(\"[\", paste(test$geoNetwork, collapse = \",\"), \"]\") %>% fromJSON(flatten = T)\nte_totals <- paste(\"[\", paste(test$totals, collapse = \",\"), \"]\") %>% fromJSON(flatten = T)\nte_trafficSource <- paste(\"[\", paste(test$trafficSource, collapse = \",\"), \"]\") %>% fromJSON(flatten = T)\n\n#Combine to make the full training and test sets\ntrain <- train %>%\n    cbind(tr_device, tr_geoNetwork, tr_totals, tr_trafficSource) %>%\n    select(-device, -geoNetwork, -totals, -trafficSource)\n    \ntest <- test %>%\n    cbind(te_device, te_geoNetwork, te_totals, te_trafficSource) %>%\n    select(-device, -geoNetwork, -totals, -trafficSource)\n\n#Remove temporary tr_ and te_ sets\nrm(tr_device)\nrm(tr_geoNetwork)\nrm(tr_totals)\nrm(tr_trafficSource)\nrm(te_device)\nrm(te_geoNetwork)\nrm(te_totals)\nrm(te_trafficSource)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"fe104b2cab47c1c73fce18893e8fa8c9308313ca"},"cell_type":"code","source":"#already converting some character variables into factors\nfactorVars <- c(\"channelGrouping\", \"browser\", \"operatingSystem\", \"deviceCategory\", \"country\")\ntrain[, factorVars] <- lapply(train[, factorVars], as.factor)\ntest[, factorVars] <- lapply(test[, factorVars], as.factor)\n\n#also converting the data variable to the date format\ntrain$date <- ymd(train$date)\ntest$date <- ymd(test$date)\n\n#converting character variables into numeric\nnumVars <- c(\"visits\", \"hits\", \"bounces\", \"pageviews\", \"newVisits\")\ntrain[, numVars] <- lapply(train[, numVars], as.integer)\ntrain$transactionRevenue <- as.numeric(train$transactionRevenue)\ntest[, numVars] <- lapply(test[, numVars], as.integer)\n\n#converting visit start times to POSIXct\ntrain$visitStartTime <- as.POSIXct(train$visitStartTime, tz=\"UTC\", origin='1970-01-01')\ntest$visitStartTime <- as.POSIXct(test$visitStartTime, tz=\"UTC\", origin='1970-01-01')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"22b72aaadf0be00f30eec732b123df234255082a"},"cell_type":"markdown","source":"# 2. EDA\n\nBelow, you can see that we have over 900,000 observations in the train set. Each observation is in fact one visit to Gstore."},{"metadata":{"trusted":true,"_uuid":"4ff414c73ea3a8037be4ed07c8939c00a8f060e2"},"cell_type":"code","source":"glimpse(train)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f67cb123c6e05d437355b4327b98c8f5afdb708d"},"cell_type":"markdown","source":"SessionId should be the unique identifier for each observation as it is a combination of fullVisitorId and visitId (which is basically the visitStartTime before I converted it to POSIXct).  The number of unique sessionId's comes close to the total number of observations (903,653), but is 898 short."},{"metadata":{"trusted":true,"_uuid":"068ed28beec28f10a13a7491a06a8e19173e280e"},"cell_type":"code","source":"n_distinct(train$sessionId)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"983468c708c0497f06eab71b3047f433b1ff874b"},"cell_type":"markdown","source":"Let's see how we fare if I look at the sessionId's that are duplicate (n=2). As you can see this explains it perfectly! We have 898 sessionId's that appear exactly twice in the train set (898*2=1796). To do: see if I need to remove duplicate sessions, or possibly consolidate some numbers (number of pagehits, session duration etc.)"},{"metadata":{"trusted":true,"_uuid":"50322ace190b0a37946e14fe456eb192636426de"},"cell_type":"code","source":"train %>% count(sessionId) %>% filter(n==2) %>% summarize(sum(n))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a2c8b06ed6cfafe6d01c80a1a64fdb2b67efa56c"},"cell_type":"markdown","source":"The test set has over 800,000 observations with two variables less (transactionRevenue and campaignCode)."},{"metadata":{"trusted":true,"_uuid":"b9669739affa804c319f887f1f1d5127564e0171"},"cell_type":"code","source":"dim(test)\nsetdiff(names(train), names(test))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a436a11473ebc3dae2549e2de618bbe8d2a7ddbd"},"cell_type":"markdown","source":"## 2.1 Missing data\n\nAltogether 14 variables in the train set contain missing values. Most of these variables seem related to adWords campaigns. The missing transactionRevenues must mean that there was no transaction."},{"metadata":{"trusted":true,"_uuid":"95d482c91c4e6ebeb818136decb500634d8079a0"},"cell_type":"code","source":"options(repr.plot.height=4)\nNAcol <- which(colSums(is.na(train)) > 0)\nNAcount <- sort(colSums(sapply(train[NAcol], is.na)), decreasing = TRUE)\nNADF <- data.frame(variable=names(NAcount), missing=NAcount)\nNADF$PctMissing <- round(((NADF$missing/nrow(train))*100),1)\nNADF %>%\n    ggplot(aes(x=reorder(variable, PctMissing), y=PctMissing)) +\n    geom_bar(stat='identity', fill='blue') + coord_flip(y=c(0,110)) +\n    labs(x=\"\", y=\"Percent missing\") +\n    geom_text(aes(label=paste0(NADF$PctMissing, \"%\"), hjust=-0.1))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"a442e52c6d1b987af50e21b299d18f49ff899a0b"},"cell_type":"markdown","source":"## 2.2 The response variable; transactionRevenue\n\nOnly 11, 515 sessions in the train set led to a transaction. This is only 1.27% of the observations, and that of course matches with the 98.7% missing values in the previous section. Altogether, GStore had 1,5 million USD revenues in that year."},{"metadata":{"trusted":true,"_uuid":"730f3be4c995e55a1a175fffbfa72b9c6ab15fad"},"cell_type":"code","source":"#setting missing values to zero\ntrain$transactionRevenue[is.na(train$transactionRevenue)] <- 0\n\n#correcting transaction revenues (see https://www.kaggle.com/c/google-analytics-customer-revenue-prediction/discussion/65775). This is for EDA purposes only. In the competition, we need to predict the log of the tranaction values as they are stored in the dataset (so not divided by 1,000,000).\ny <- train$transactionRevenue #saving original values in a vector\ntrain$transactionRevenue <- train$transactionRevenue/1000000\n\n\ntrain %>% filter(transactionRevenue >0) %>% summarize('number of transactions'=n(), 'total revenues train set'=sum(transactionRevenue))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d9f9b82611209a9f92ab8af2a25ecd985484946f"},"cell_type":"markdown","source":"The range of revenues per transaction is from 1 dollarcent to 23,129.5 USD. Of the 11,515 transactions, 195 had revenues of at least 1,000 USD. The sum of revenues of this tail of big transactions is about 418,000 USD."},{"metadata":{"trusted":true,"_uuid":"a4cdbbddbce4144b2891fd770d5ab135b45839f3"},"cell_type":"code","source":"range(train %>% select(transactionRevenue) %>% filter(transactionRevenue !=0))\ntrain %>% filter(transactionRevenue>=1000) %>% summarize('number of transactions with at least 1000 USD revenues'=n(), 'sum revenues of transactions with at least 1000 USD revenues'=sum(transactionRevenue))\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6cdd1f2151c8074399b0d881075d09912b2f8509"},"cell_type":"markdown","source":"As the distribution of revenues is very right skewed, with the tail reaching 23,000 USD, I am below only displaying the histogram of the transaction with revenues below 1,000 USD."},{"metadata":{"trusted":true,"_uuid":"e0a04a87369f166ff6296b53c7acecf855fbce36"},"cell_type":"code","source":"options(repr.plot.height=4)\ntrain %>% filter(transactionRevenue >0 & transactionRevenue<1000) %>%\nggplot(aes(x=transactionRevenue)) +\n        geom_histogram(fill=\"blue\", binwidth=10) +\n        scale_x_continuous(breaks= seq(0, 1000, by=100), labels = comma)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b60f35e95aed8da4224e40fb02e2ce41ab26d5ca"},"cell_type":"markdown","source":"## 2.3 Time series and grouping by workday and by month\nWe have one year of train data (August 1, 2016-August 1, 2017), and 9 month of test data (August 2, 2017-April 30 2018)."},{"metadata":{"trusted":true,"_uuid":"6aac15fb13960a6930926c1508772ccfd7841a7f"},"cell_type":"code","source":"range(train$date)\nrange(test$date)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"9bc80e2690edb21d89aa3eb35a69f8652736a293"},"cell_type":"markdown","source":"### 2.3.1 Time series of sessions and revenues by Date\nThe number of daily sessions peaked in October and November 2016, but this did not lead to higher daily revenues. In the revenues plot,  we see daily revenues vary between 0 and about 27,000 USD and that there is no real revenues trend visible. In addition, we see some outliers with high daily revenues. For instance, the high daily revenue somewhere in the beginning of April 2017. Was there a special reason for this? Maybe there was a special event, or one very big transaction?"},{"metadata":{"trusted":true,"_uuid":"b9722474da1d13e82c90e0087861f985d471e51e"},"cell_type":"code","source":"options(repr.plot.height=6)\nd1 <- train %>% group_by(date) %>% summarise(dailySessions = n()) %>%\n    ggplot(aes(x=date, y=dailySessions)) + geom_line(col='blue') +\n    scale_y_continuous(labels=comma) + geom_smooth(col='red') +\n    labs(x=\"\", y=\"Sessions per Day\") + scale_x_date(date_breaks = \"1 month\", date_labels = \"%b %d\")\nd2 <- train %>% group_by(date) %>% summarise(dailyRevenue = sum(transactionRevenue)) %>%\n    ggplot(aes(x=date, y=dailyRevenue)) + geom_line(col='blue') +\n    scale_y_continuous(labels=comma) + geom_smooth(col='red') +\n    labs(x=\"\", y=\"Daily Revenues (USD)\") + scale_x_date(date_breaks = \"1 month\", date_labels = \"%b %d\")\ngrid.arrange(d1,d2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"5ee093e53e14612de757d16adc136b1483c35a90"},"cell_type":"markdown","source":"### 2.3.2 Sessions and revenues by Workday\nFirst of all, I am creating a new variable from the Date variable with the `wday` function of lubridate."},{"metadata":{"trusted":true,"_uuid":"3af601325b75b5fb23173089aeabc7c124776d32"},"cell_type":"code","source":"train$weekday <- wday(train$date, label=TRUE)\ntest$weekday <- wday(test$date, label=TRUE)\nstr(train$weekday)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"eeccd0ab1d41d3d9d442b765a8640ec7fe0b8a72"},"cell_type":"markdown","source":"The next thing that I am doing is that I create two functions that allow me to create barplots for all factor variables quickly."},{"metadata":{"trusted":true,"_uuid":"27135da930dabf4b8ccd445a99b03ba8ac76e2c4"},"cell_type":"code","source":"#Note: I have not included reordering of x in this function. First of all, I don't want to reorder the workday and month plots.\n#Second: Manual reordering gave me the opportunity to order the Revenues in the same order as first plot (descreasing sessions). See for instance Channel Grouping.\n#The adjusted functions to display plots with flipped x and y (see section 2.4.2 the source/medium dimension) includes reordering.\n\nplotSessions <- function(dataframe, factorVariable, topN=10) {\n    var_col <- enquo(factorVariable)\n    dataframe %>% count(!!var_col) %>% top_n(topN, wt=n) %>%\n    ggplot(aes_(x=var_col, y=~n, fill=var_col)) +\n    geom_bar(stat='identity')+\n    scale_y_continuous(labels=comma)+\n    labs(x=\"\", y=\"number of sessions\")+\n    theme(legend.position=\"none\")\n    }\n\n#also creating a function to plot transactionRevenue for a factorvariable\nplotRevenue <- function(dataframe, factorVariable, topN=10) {\n    var_col <- enquo(factorVariable)\n    dataframe %>% group_by(!!var_col) %>% summarize(rev=sum(transactionRevenue)) %>% filter(rev>0) %>% top_n(topN, wt=rev) %>% ungroup() %>%\n    ggplot(aes_(x=var_col, y=~rev, fill=var_col)) +\n    geom_bar(stat='identity')+\n    scale_y_continuous(labels=comma)+\n    labs(x=\"\", y=\"Revenues (USD)\")+\n    theme(legend.position=\"none\")\n    }","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"dd694bdc8d21c5c0291aa2f62dafb03830aa47aa"},"cell_type":"markdown","source":"Initially, I was a bit surprised to see that there are less sessions and revenues in weekend. However, a logical explanation to me seems that Google Swag is mostly bought by businesses rather than private individuals!\n\nMain takeaway for modeling: The point here is that weekend sessions led to less revenues in general (numbers of sessions on Saterday/Sunday are smaller than those on weekdays, but revenues are much smaller)."},{"metadata":{"trusted":true,"_uuid":"fcc41173e66d1d44e55c008d78c075a2b17a1ef2"},"cell_type":"code","source":"options(repr.plot.height=4)\nw1 <- plotSessions(train, weekday)\nw2 <- plotRevenue(train, weekday)\ngrid.arrange(w1, w2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"674b6a056f68ca5ab86609812deb90ceca46b647"},"cell_type":"markdown","source":"### 2.3.3 Sessions and revenues by Month\nBelow, I am repeating the trick from the previous session for `month`. Patterns are less clear to me, but months seems to matter. For instance, April has a high ratio of revenues/sessions, and this ratio is low for November."},{"metadata":{"trusted":true,"_uuid":"b8b1937516bf70abfc67a649cfb1339670f2e88a"},"cell_type":"code","source":"options(repr.plot.height=4)\n\ntrain$month <- month(train$date, label=TRUE)\ntest$month <- month(test$date, label=TRUE)\n\n\nm1 <- plotSessions(train, month, 12)\nm2 <- plotRevenue(train, month, 12)\ngrid.arrange(m1, m2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8871f07342d32c2f1d9e2999cefaf8b778fda68a"},"cell_type":"markdown","source":"## 2.4 Channel grouping and the source/medium dimension\n\n### 2.4.1 Channel grouping\nChannels define how users come to your website (Channel Groupings are rule-based groupings of your traffic sources). The default channel groupings can be found [here](https://support.google.com/analytics/answer/3297892). These groups are mostly defined by the `Medium`, and some also by  `Source`, `Social Source Referral` or `Ad Distribution Network`. From Google Analytics:\n\n* Source: the origin of your traffic, such as a search engine (for example, google) or a domain (example.com).\n* Medium: the general category of the source, for example, organic search (organic), cost-per-click paid search (cpc), web referral (referral).\n\nExamples:\n* Organic Search is defined by the medium only (Medium exactly matches organic).\n* Referral is also defined by the medium only (Medium exactly matches referral).\n* Social: Social Source Referral exactly matches Yes OR Medium matches regex ^(social|social-network|social-media|sm|social network|social media)$\n* Direct: Source exactly matches direct AND Medium exactly matches (not set) OR Medium exactly matches (none)\n\nAs you see in the plots, Organic Search and Social led to many sessions, but especially Social delivers hardly any revenues. Referral on the other hand delivers most revenues with a relatively small number of sessions."},{"metadata":{"trusted":true,"_uuid":"c99274e447f586ff69161f55590f12f353575993"},"cell_type":"code","source":"options(repr.plot.height=6)\n\n#adding reordering of x manually\nsessionOrder <- train %>% count(channelGrouping) %>% top_n(10, wt=n) %>% arrange(desc(n))\nsessionOrder <- sessionOrder$channelGrouping\n\nc1 <- plotSessions(train, channelGrouping) + scale_x_discrete(limits=sessionOrder)\nc2 <- plotRevenue(train, channelGrouping) + scale_x_discrete(limits=sessionOrder)\ngrid.arrange(c1, c2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3eb9858062f0b562f6131a0fb5ef1f97a1e9682d"},"cell_type":"markdown","source":"### 2.4.2 The source/medium dimension\nSource/Medium is a dimension that combines the dimensions Source and Medium. Examples of Source/Medium include google/organic, example.com/referral, and newsletter9-2014/email.\n\nAs I now wanted to flip the axis, I adjusted the plot functions first in the code below."},{"metadata":{"_kg_hide-input":true,"trusted":true,"_uuid":"debd01a7c7e26c915ae50ce4bd4eac9a4554eec2"},"cell_type":"code","source":"#Note: I am using a bit of a hack to add reordering to these functions as reorder works with the normal aes() but does seem to work with aes_q()\n\nplotSessionsFlip <- function(dataframe, factorVariable, topN=10) {\n    var_col <- enquo(factorVariable)\n    x <- dataframe %>% count(!!var_col) %>% top_n(topN, wt=n) %>% arrange(n)\n    y <- x[[1]]\n    x %>% ggplot(aes_(x=var_col, y=~n)) + coord_flip() +\n    geom_bar(stat='identity', fill=\"orange\")+\n    scale_y_continuous(labels=comma)+\n    labs(x=\"\", y=\"number of sessions\")+\n    theme(legend.position=\"none\") +\n    scale_x_discrete(limits=y)\n    }\n\nplotRevenueFlip <- function(dataframe, factorVariable, topN=10) {\n    var_col <- enquo(factorVariable)\n    x <- dataframe %>% group_by(!!var_col) %>% summarize(rev=sum(transactionRevenue)) %>% filter(rev>0) %>% top_n(topN, wt=rev) %>% arrange(rev) %>% ungroup()\n    y <- x[[1]]\n    x %>% ggplot(aes_(x=var_col, y=~rev)) + coord_flip() +\n    geom_bar(stat='identity', fill=\"orange\")+\n    scale_y_continuous(labels=comma)+\n    labs(x=\"\", y=\"Revenues (USD)\")+\n    theme(legend.position=\"none\") +\n    scale_x_discrete(limits=y)\n    }","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"c06cdcbfb4da0ccd2c872f34571b0c789e3bdcee"},"cell_type":"markdown","source":"Below, I am first creating this dimension. It is very interesting to see that for instance \"youtube.com/referral\" generates a lot of traffic, but that this combi is not in the Top20 of most revenues. On the other hand, \"mall.googleplex.com/referral\" generates a modest amount of sessions but it is the source/medium with most revenues!"},{"metadata":{"trusted":true,"_uuid":"9b49675aef2051b3cd68345aedc66ab6f42a2360"},"cell_type":"code","source":"train$sourceMedium <- paste(train$source, train$medium, sep=\"/\")\ntest$sourceMedium <- paste(test$source, test$medium, sep=\"/\")\n\ns1 <- plotSessionsFlip(train, sourceMedium, 20) + theme(axis.text.x = element_text(angle = 45, hjust = 1))\ns2 <- plotRevenueFlip(train, sourceMedium, 20) + theme(axis.text.x = element_text(angle = 45, hjust = 1))\ngrid.arrange(s1, s2, nrow=1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"aeb177e09212ed7645023692dc113ea4eddf3c29"},"cell_type":"markdown","source":"## 2.5 Operating system, browser and device category\n\n### 2.5.1 Device category\nThe main takeaway here is that mobile and tablet have a lot fewer sessions, and relatively low revenues per session when compared to desktop."},{"metadata":{"trusted":true,"_uuid":"39525137c76e5a3917cc71be99956f2c2657a5ac"},"cell_type":"code","source":"options(repr.plot.height=5)\nd1 <- plotSessions(train, deviceCategory)\nd2 <- plotRevenue(train, deviceCategory)\ngrid.arrange(d1, d2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d61c1bfe587c9f9b9e23acee7a27617d80371c03"},"cell_type":"markdown","source":"### 2.5.2 Operating System\nSince there are only 7 Operating Systems with revenues, I am only displaying those. Actually, (not set) had slightly more sessions than Windows Phone, but since (not set) is pretty meaningless and (not set) had no revenues anyway, I excluded (not set) from the first plot.\n\nWhat stands out is Macintosh had much higher revenues than Windows with fewer sessions. In addition, it also confirms again that the mobile sessions (Android and iOS) have little revenues compared to the number of sessions."},{"metadata":{"_uuid":"22d1c0632aecaa0351fcfd21131e161e2dd7a14b","trusted":true},"cell_type":"code","source":"options(repr.plot.height=5)\n\nsessionOrder <- train %>% filter(operatingSystem != \"(not set)\") %>% count(operatingSystem) %>% top_n(7, wt=n) %>% arrange(desc(n))\nsessionOrder <- sessionOrder$operatingSystem\n\no1 <- plotSessions(train %>% filter(operatingSystem != \"(not set)\"), operatingSystem, 7) + scale_x_discrete(limits=sessionOrder)\no2 <- plotRevenue(train, operatingSystem) + scale_x_discrete(limits=sessionOrder)\ngrid.arrange(o1, o2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"4d483c1366f2b46ccbb16150a121697ea8075b37"},"cell_type":"markdown","source":"### 2.5.3 Browser\nWhile the first plot displays the top10 browsers with most sessions (n=10 is the default in the function), the second plot only displays 9 browsers as there were only 9 browsers with revenues. By far the most sessions and revenues come from the Chrome browser. Firefox also has a healthy balance between sessions and revenue. Safari has a lot of sessions with relatively low revenues."},{"metadata":{"trusted":true,"_uuid":"15b56aef8c8e90868adf0b19113a7d1e296bb35b"},"cell_type":"code","source":"options(repr.plot.height=5)\n\nd1 <- plotSessionsFlip(train, browser)\nd2 <- plotRevenueFlip(train, browser)\ngrid.arrange(d1, d2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8ef77f229c7468dab47bd634fbef5268e5e81615"},"cell_type":"markdown","source":"## 2.6 Pageviews, Bounces and Hits\n\n### 2.6.1 Pageviews; all sessions.\n\n>A pageview is each time a visitor views a page on your website, regardless of how many hits are generated.\n\nThe distribution of pageviews is very right skewed. However, the second graph shows that most revenues come from (small) numbers of sessions with lots of pageviews!"},{"metadata":{"trusted":true,"_uuid":"e833bd14896fb07f29dc38a4913eac50052faa6e"},"cell_type":"code","source":"options(repr.plot.height=4)\n#sessions with more than 28 pageviews all have frequencies of less than 1,000. Since these are hardly visible, I am excluding them.\n#excluding 100 pageview NAs\n\np1 <- train %>% filter(!is.na(train$pageviews) & pageviews <=28) %>% \nggplot(aes(x=pageviews)) +\n    geom_histogram(fill='blue', binwidth=1) +\n    scale_y_continuous(breaks=seq(0, 500000, by=100000), label=comma) +\n    scale_x_continuous(breaks=seq(0, 28, by=5)) +\n    coord_cartesian(x=c(0,28))\n\np2 <- train %>% filter(!is.na(train$pageviews) & pageviews <=28) %>% group_by(pageviews) %>%\n    ggplot(aes(x=pageviews, y=transactionRevenue)) +\n    geom_bar(stat='summary', fun.y = \"sum\", fill='blue') +\n    scale_x_continuous(breaks=seq(0, 28, by=5)) +\n    coord_cartesian(x=c(0,28)) + labs(y=\"sum of revenues\")\ngrid.arrange(p1, p2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"009425581f953e06494d8382fa873288600340ea"},"cell_type":"markdown","source":"Below, I am taking the mean of the revenues per session for each pageview 'category'. For the mean, we are getting some decent numbers. Not surprsingly, the medain is 0 for all those pageview categories."},{"metadata":{"trusted":true,"_uuid":"d47f7913b743bb9e464099c0e21bbb85dd24fd7b"},"cell_type":"code","source":"p1 <- train %>% filter(!is.na(train$pageviews) & pageviews <=28) %>% group_by(pageviews) %>%\n    ggplot(aes(x=pageviews, y=transactionRevenue)) +\n    geom_bar(stat='summary', fun.y = \"mean\", fill='blue') +\n    scale_x_continuous(breaks=seq(0, 28, by=5)) +\n    coord_cartesian(x=c(0,28)) + labs(y=\"mean of revenues\")\np2 <- train %>% filter(!is.na(train$pageviews) & pageviews <=28) %>% group_by(pageviews) %>%\n    ggplot(aes(x=pageviews, y=transactionRevenue)) +\n    geom_bar(stat='summary', fun.y = \"median\", fill='blue') +\n    scale_x_continuous(breaks=seq(0, 28, by=5)) +\n    coord_cartesian(x=c(0,28)) + labs(y=\"median of revenues\")\ngrid.arrange(p1, p2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8d23fa07be073726d9c1b71d75c8b50cf6ac0856"},"cell_type":"markdown","source":"### 2.6.2 Pageviews; only sessions with any transaction revenue.\nBelow I displaying the histogram of **pageviews with revenues**. This mean that we are only looking at the 11,515 sessions with revenues. This paints a very different picture!"},{"metadata":{"trusted":true,"_uuid":"6ea97d6af3d2529fa2d2494e5a3e6bb62e82bc1c"},"cell_type":"code","source":"train %>% filter(!is.na(train$pageviews) & pageviews <=28 & transactionRevenue>0) %>% \nggplot(aes(x=pageviews)) +\n    geom_histogram(fill='blue', binwidth=1) +\n    scale_x_continuous(breaks=seq(0, 28, by=5)) +\n    coord_cartesian(x=c(0,28)) +\n    labs(y='number of session with transaction revenue')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"459e14d27dea9ad92530ac8bc3f5f097ed8f1be4"},"cell_type":"markdown","source":"I am now adding transactionRevenue>0 to the filter, and display the mean and median revenues of the sessions with some transaction revenue only. It would say that let's say the mean and median of the categories up-to 7 pageviews are very unreliable as these are based on only 0-25 transactions (of large numbers of sessions)."},{"metadata":{"trusted":true,"_uuid":"68dd8286ad4b8609a406144e7fe12747de3bf9da"},"cell_type":"code","source":"p1 <- train %>% filter(!is.na(train$pageviews) & pageviews <=28 & transactionRevenue>0) %>% group_by(pageviews) %>%\n    ggplot(aes(x=pageviews, y=transactionRevenue)) +\n    geom_bar(stat='summary', fun.y = \"mean\", fill='blue') +\n    scale_x_continuous(breaks=seq(0, 28, by=5)) +\n    coord_cartesian(x=c(0,28)) + labs(y=\"mean of revenues\") +\n    geom_label(stat = \"count\", aes(label = ..count..), y=0, size=2)\np2 <- train %>% filter(!is.na(train$pageviews) & pageviews <=28 & transactionRevenue>0) %>% group_by(pageviews) %>%\n    ggplot(aes(x=pageviews, y=transactionRevenue)) +\n    geom_bar(stat='summary', fun.y = \"median\", fill='blue') +\n    scale_x_continuous(breaks=seq(0, 28, by=5)) +\n    coord_cartesian(x=c(0,28)) + labs(y=\"median of revenues\") +\n    geom_label(stat = \"count\", aes(label = ..count..), y=0, size=2)\ngrid.arrange(p1, p2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ce7d3ba6712548d70481e67e9cd2e235c5b455e7"},"cell_type":"markdown","source":"### 2.6.3 Pageviews versus percent transactions\nAfter having made all these revenue-related plots, a last thing that I wanted to figure out was the percent of transaction (regardless of the transaction revenue amount) for each category of pageviews. All sessions with less than 7 pageviews led to zero or a negligable percent of transactions! As you can see, there seems to be a correlation but only among pageviews of let's say at least 7-40/50 pageviews. Above 40/50 pageviews the percent transactions remain flat."},{"metadata":{"trusted":true,"_uuid":"5a8144060e912c3508d4cabbbfd80313780c981f"},"cell_type":"code","source":"train$transaction <- ifelse(train$transactionRevenue > 0, 1, 0)\n\ntrain %>% filter(!is.na(train$pageviews) & pageviews <=100) %>% group_by(pageviews) %>%\nsummarize('sessions'= n(), 'transactions'= sum(transaction), 'pctTransactions'=round(x=((transactions/sessions)*100),digits=1)) %>%\n    ggplot(aes(x=pageviews, y=pctTransactions)) +\n    geom_bar(stat='identity', fill='blue') +\n    scale_x_continuous(breaks=seq(0, 100, by=5)) +\n    geom_smooth()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"78b5c61894c13d93ebed9c237ee596de40800470"},"cell_type":"markdown","source":"### 2.6.4 Bounces\n\n>A bounce is a single-page session on your site.\n\nSince a bounce is the same as a 'one pageview session'. Therefore, I am just checking if these numbers match."},{"metadata":{"trusted":true,"_uuid":"f79d2cbf6c5e43c76fc994df5f3d6d14be42048d"},"cell_type":"code","source":"#setting missing values to zero (percent missing in train is 50.1%)\ntrain$bounces[is.na(train$bounces)] <- 0L\ntest$bounces[is.na(test$bounces)] <- 0L\ntrain %>% filter(bounces==1) %>% summarize('number of bounces'=n(), 'revenues bounce sessions'=sum(transactionRevenue))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"f157879d69b178c348222f9634487de40c1834ef"},"cell_type":"markdown","source":"So we have 450,630 bounces. However, below you can see that we have 452,522 sessions with 1 pageview. This number should be the same! \n\nAs a bounce is a 1-page session, it should never have any revenues (A transaction needs at least 2 pageviews: first you would have to select a product, then move on to a page on which you can pay). Above, you can see that this is correct for all sessions that are labeled as a bounce. However, you can see that the zero revenues are also correct for the 452,522 sessions with pageviews==1. Therefore, I think we can fix this discrepancy with setting all those 1-page session to bounce==1."},{"metadata":{"trusted":true,"_uuid":"0f9c7713aee3fce62cffb87dd6a5cccc18dd1ec4"},"cell_type":"code","source":"train %>% filter(pageviews==1) %>% summarize('number of 1-page sessions'=n(), 'revenues 1-page session'=sum(transactionRevenue))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"43fd8e6dc705b5c54b5f085a330557985f72d0c4"},"cell_type":"markdown","source":"### 2.6.5 Hits\nThe first definition that I found was:\n\n>Hit: Pages are comprised of files. For example, if you have a page with 10 pictures, then a request to a server to view that page generates 11 hits (10 for the pictures, and one for the html file).\n\nThat did not sound as a reliable predictor to me. However, there was an interesting finding in this discussion topic: [Finding - Pageviews/Hits ratio <0.4 guarantees no revenue](https://www.kaggle.com/c/ga-customer-revenue-prediction/discussion/66774). I was pointed to another definition:\n\n>Hit: An interaction that results in data being sent to Analytics. Common hit types include page tracking hits, event tracking hits, and ecommerce hits. Each time the tracking code is triggered by a user’s behavior (for example, user loads a page on a website or a screen in a mobile app), Analytics records that activity. Each interaction is packaged into a hit and sent to Google’s servers. Examples of hit types include: page tracking hits, event tracking hits, ecommerce tracking hits, social interaction hits.\n\nThis made me believe that I should look at hits after all. The graph below shows a pattern that is very similar to the one of pageviews (no transactions for very few hits/pages, a correlation from x to y, and flat after that). Therefore, looking at the pageviews/hits ratio seems a good idea to me indeed! The second graph confirms the finding in the discussion topic (please notice that I have zoomed-in a lot make small amounts more visible)!\n"},{"metadata":{"trusted":true,"_uuid":"e136e113debd94beff2b1410fdd9c74c7ae55808"},"cell_type":"code","source":"h1 <- train %>% filter(hits <=200) %>% group_by(hits) %>%\nsummarize('sessions'= n(), 'transactions'= sum(transaction), 'pctTransactions'=round(x=((transactions/sessions)*100),digits=1)) %>%\n    ggplot(aes(x=hits, y=pctTransactions)) +\n    geom_bar(stat='identity', fill='blue') +\n    geom_smooth()\n\ntrain$ratioPageHits <- train$pageviews/train$hits\n\nh2 <- train %>% filter(!is.na(pageviews)) %>%\n    ggplot(aes(x=ratioPageHits, y=transactionRevenue)) +\n    geom_line(stat='identity', col='blue') +\n    coord_cartesian(y=c(0,100)) +\n    scale_x_continuous(breaks=seq(0, 1, by=0.1))\n\ngrid.arrange(h1, h2)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"24460f5fa5ba2abd7992c2314b76862ebfc21ba8"},"cell_type":"markdown","source":"## 2.7 Sessions, revenues and transactions by country\nThe US really dwarf all other countries with regards to the number of sessions and the total revenues."},{"metadata":{"trusted":true,"_uuid":"b7e04f9fae59655fa54997d2733790f43b23c0f6"},"cell_type":"code","source":"c1 <- plotSessionsFlip(train, country, 20)\nc2 <- plotRevenueFlip(train, country, 20)\ngrid.arrange(c1, c2, nrow=1)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6d004317d81f64100b144efbf61e298eef5bb4eb"},"cell_type":"markdown","source":"Only 10 countries have at least 100 sessions and at least 10 transaction, and only 4 of those countries have mean revenues per session of more than 1 USD. Mean revenues per transaction vary between 79 and 395 USD. However, we must realize that of the 11,515 transactions, almost all come from the US (10,953)."},{"metadata":{"trusted":true,"_uuid":"2001cf6b2fff559e6cb56d81ad557d1bb29a6562"},"cell_type":"code","source":"train %>% group_by(country) %>%\nsummarize(sessions= n(), transactions=sum(transaction), totalRev=sum(transactionRevenue), sessionMean=totalRev/sessions, transactionMean=totalRev/transactions) %>%\nfilter(sessions>100 & transactions>10) %>% top_n(20, wt=sessionMean) %>% arrange(desc(sessionMean))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"80b555bcb77308ec5abc0d9bdefc472a39e72416"},"cell_type":"markdown","source":"# 3. LightGBM Model\nPlease be aware that this is just a baseline model. It needs to be further optimized by Feature Engineering and Hyperparameter tuning. I have used some tips and tricks from kxx's kernel. Many thanks kxx!\n\nI am using the last two months of the train set as my validation set."},{"metadata":{"trusted":true,"scrolled":true,"_uuid":"582d4e56de6eb781af529efd95c779440195664f"},"cell_type":"code","source":"train <- train %>% select(-one_of(c(\"campaignCode\", \"transaction\", \"ratioPageHits\")))\n\nfea_uniq_values <- sapply(train, n_distinct)\n(fea_del <- names(fea_uniq_values[fea_uniq_values == 1]))\n\ntrain <- train %>% select(-one_of(fea_del))\ntest <- test %>% select(-one_of(fea_del))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"f9c27fbb53fe8a6a4f319da8c7d54e493f7b4b1f"},"cell_type":"code","source":"train$transactionRevenue <- train$transactionRevenue*1000000\ntrain$pageviews[is.na(train$pageviews)] <- 0L\ntest$pageviews[is.na(test$pageviews)] <- 0L\nidPageBounce <- test[, c(\"fullVisitorId\", \"pageviews\", \"bounces\")]\ntrainIndex <- 1:nrow(train)\nsplitTrainValidDate <- ymd(\"20170601\")\n\ntrainLabel <- log1p(train$transactionRevenue[train$date < splitTrainValidDate])\nvalLabel <- log1p(train$transactionRevenue[train$date >= splitTrainValidDate])\ntrain$transactionRevenue <- NULL\n\n#merging train and test do do some cleanup\nall <- as.tibble(rbind(train, test))\n\nis_na_val <- function(x) x %in% c(\"not available in demo dataset\", \"(not provided)\",\n                                  \"(not set)\", \"<NA>\", \"unknown.unknown\",  \"(none)\")\n\nall <- all %>% mutate_all(funs(ifelse(is_na_val(.), NA, .)))\n\nall <- all %>% mutate(isMobile = ifelse(isMobile, 1L, 0L),\n            isTrueDirect = ifelse(isTrueDirect, 1L, 0L),\n            adwordsClickInfo.isVideoAd = ifelse(!adwordsClickInfo.isVideoAd, 0L, 1L))\n\n#There seems to be an issue with date and POSIXct after rbind\nall$visitStartTime <- as.POSIXct(all$visitStartTime, tz=\"UTC\", origin='1970-01-01')\nall$date <- as.Date(all$date, origin='1970-01-01')\n\n#new feature\nall$sessionHourOfDay <- hour(all$visitStartTime)\n\nall <- all %>%\nselect(-fullVisitorId, -visitId, -sessionId, -visitStartTime) %>% \nmutate_if(is.character, factor)\n\n#keeping vector of categorical features for LGB\ncategorical_feature <- names(Filter(is.factor, all))\n\n#Label encoding\nall <- all %>% \n  mutate_if(is.factor, as.integer) %>% \n  glimpse()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"021213789f66c176ddb2bfb5830403cc4c6be964"},"cell_type":"code","source":"#splitting all into train, validation, and test set\ndtrain <- all[trainIndex,]\ndtest <- all[-trainIndex,]\ndval <- dtrain[dtrain$date >= splitTrainValidDate,]\ndtrain <- dtrain[dtrain$date < splitTrainValidDate,]\n\ndtest$date <- NULL\ndtrain$date <- NULL\ndval$date <- NULL","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"5923de03fd36a03fd0f06bdee516d939d12a08a9"},"cell_type":"code","source":"set.seed(123)\n\nlgb.train = lgb.Dataset(data=as.matrix(dtrain),label=trainLabel, categorical_feature =categorical_feature)\nlgb.valid = lgb.Dataset(data=as.matrix(dval),label=valLabel, categorical_feature =categorical_feature)\n\nparams <- list(objective=\"regression\",\n              metric=\"rmse\",\n              learning_rate=0.01)\n\nlgb.model <- lgb.train(params = params,\n                       data = lgb.train,\n                       valids = list(val = lgb.valid),\n                       learning_rate=0.01,\n                       nrounds=1000,\n                       verbose=1,\n                       early_stopping_rounds=50,\n                       eval_freq=100\n                      )\n\nlgb.model$best_iter\nlgb.model$best_score ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"764e2f666cb009ba7b1af817a170824656f0c0d6"},"cell_type":"code","source":" tree_imp <- lgb.importance(lgb.model, percentage = TRUE)\n lgb.plot.importance(tree_imp, top_n = 50, measure = \"Gain\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"7f02ac0bb7d8d204b821f879d196c7ca6bbd2499","_kg_hide-output":true},"cell_type":"code","source":"pred <- predict(lgb.model, as.matrix(dtest)) %>% \n  as_tibble() %>% \n  set_names(\"y\") %>% \n  mutate(y = expm1(y)) %>% \n  mutate(y = ifelse(y < 0, 0, y))\npred <- cbind(pred, idPageBounce)\npred <- pred %>%\n  mutate(y = ifelse((pageviews<7|bounces==1), 0, y))\npred <- pred %>% select(-pageviews, -bounces) %>%\n  group_by(fullVisitorId) %>% \n  summarise(y = log1p(sum(y)))\n\nread_csv(\"../input/sample_submission.csv\") %>%  \n  left_join(pred, by = \"fullVisitorId\") %>% \n  mutate(PredictedLogRevenue = round(y, 5)) %>% \n  select(-y) %>% \n  write_csv(paste0(\"Lightgbm\",round(lgb.model$best_score,5),\".csv\"))","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ef24d4f55b92fde06dc2ba9bd5082da30c22a7c9"},"cell_type":"markdown","source":"The public score of this draft model is 1.46."},{"metadata":{"_uuid":"760c7933fa6c43c9d129403fd6e5f5e72ce6fca6"},"cell_type":"markdown","source":"# Appendix: Screenshots of the app\n\nThe screenshots might be helpful to people to get some sort of domain knowledge. For now, I am including screenshots of all overview reports of the main menu."},{"metadata":{"_uuid":"c3290dc06004581435e5fddd145e987b9f58d3c3"},"cell_type":"markdown","source":"## Main Screen\n\n![](https://i.imgur.com/EUlHXDs.png)"},{"metadata":{"_uuid":"06e29eb15753c4f062e041e8968f111ee1ddc329"},"cell_type":"markdown","source":"## Real-time overview\nThe Real-Time Report allows you to monitor activity as it happens on your website – e.g. how many people are on your site right now, which pages or events they're interacting with, and which goal conversions have occurred.\n\n![](https://i.imgur.com/5WadQz4.png)"},{"metadata":{"_uuid":"9cd44acfc416d66736c9e82ced0ac7bed65c364b"},"cell_type":"markdown","source":"## Audience\n\nThis report gives you a quick overview of the overall performance of the website – number of sessions,\nusers (both new and returning), page views, average session duration, bounce rate, new sessions.\n\nI have entered the date range of train+test in Google Analytics. This leads to 1,8 million sessions. Below, you can also see that the total number of observations in the train and test sets is 1,7 million. I don't know yet where the discrepancies come from, but at least the number of sessions is in the same range indeed!"},{"metadata":{"trusted":true,"_uuid":"3750c44050fe997fe3a49404e7bc5a4dfb99159c"},"cell_type":"code","source":"nrow(train)+nrow(test)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"6211fa47f5d05585bbea34e92e020a262c2dff6e"},"cell_type":"markdown","source":"![](https://i.imgur.com/WdooE8Q.png)"},{"metadata":{"_uuid":"93610b4f383b30abaf7a2068a2f943b0beb38e49"},"cell_type":"markdown","source":"## Acquisition\n\nThis report gives you a quick overview of the top channels of your website traffic – direct traffic, organic\nsearch, referral, social media, display advertising, email and paid search (i.e. AdWords) \n\n![](https://i.imgur.com/jVZ0tJ6.png)\n"},{"metadata":{"_uuid":"e05ad51cbf61446af9c343ded8ed6ebfbd9b7110"},"cell_type":"markdown","source":"## Behaviour\nThe Behavior overview report reveals what pages people visit on your website and what actions they take while visiting. It also provides information about the number of page views, bounce rate & exit rate.\n\n![](https://i.imgur.com/fetx6qV.png)"},{"metadata":{"_uuid":"775dea364f217fc93caf92b6d1896133a164ae69"},"cell_type":"markdown","source":"## Conversions\n\n![](https://i.imgur.com/0VpJu9i.png)"},{"metadata":{"_uuid":"cd3cb1e1308c00f63969921dd1bb793ab26983eb"},"cell_type":"markdown","source":""}],"metadata":{"kernelspec":{"display_name":"R","language":"R","name":"ir"},"language_info":{"mimetype":"text/x-r-source","name":"R","pygments_lexer":"r","version":"3.4.2","file_extension":".r","codemirror_mode":"r"}},"nbformat":4,"nbformat_minor":1}