diff --git a/ext/manifest.json b/ext/manifest.json index 98712ac..95b6b3b 100644 --- a/ext/manifest.json +++ b/ext/manifest.json @@ -30,7 +30,7 @@ ] } ], - "permissions": ["tabs", "https://hn.algolia.com/*"], - "content_security_policy": "script-src 'self' 'unsafe-eval' 'sha256-CfMPE8ys/ylJ5D9qKG0a9/UejrcczMr4/EmFCbVbgcc=' 'sha256-XsBu2nEJnS7x/Izq1v7dzy3Ze5myJMHvg4zukh/R1Yk=' 'sha256-AUCho1UyOpYFSZDg8EM9SYlysRIrUpQKZ7iE9CFSYfU=' 'sha256-vLlTaRFN8A2FPadIx711FwK9Ytd6LXkAzuEYAdC0D1k=' 'sha256-uM0I4me9aSUPORchT/KpGrvBQV6915H0JG2FGR5+BOs=' https://cdn.amplitude.com; object-src 'self'; connect-src 'self' https://hn.algolia.com", + "permissions": ["tabs", "storage", "https://hn.algolia.com/*"], + "content_security_policy": "script-src 'self' 'unsafe-eval' 'sha256-CfMPE8ys/ylJ5D9qKG0a9/UejrcczMr4/EmFCbVbgcc=' 'sha256-XsBu2nEJnS7x/Izq1v7dzy3Ze5myJMHvg4zukh/R1Yk=' 'sha256-AUCho1UyOpYFSZDg8EM9SYlysRIrUpQKZ7iE9CFSYfU=' 'sha256-vLlTaRFN8A2FPadIx711FwK9Ytd6LXkAzuEYAdC0D1k=' 'sha256-1UCUm5I6GtSMgMby54Gn/AsMsDl7NsPHR5fzHo5QKFk=' 'sha256-1xHe9CtNkuVwZ04dss1ckVX6f/uYjAIBCqgXQMOzxec=' https://cdn.amplitude.com; object-src 'self'; connect-src 'self' https://hn.algolia.com https://api.amplitude.com", "web_accessible_resources": ["sidebar.html", "js/*.map", "js/generated/*.map", "js/generated/out/*"] } diff --git a/src/looped_in/analytics.cljs b/src/looped_in/analytics.cljs index 0a4c09a..be7db10 100644 --- a/src/looped_in/analytics.cljs +++ b/src/looped_in/analytics.cljs @@ -1,5 +1,8 @@ (ns looped-in.analytics - (:require [goog.dom :as dom])) + (:require [goog.dom :as dom] + [cljs.core.async :refer [go chan !]] + [looped-in.promises :refer [promise->channel]] + [looped-in.logging :as log])) (goog-define amplitude-api-key "FAKE_API_KEY") @@ -16,4 +19,24 @@ [] (when (not (do-not-track)) (dom/appendChild (.-body (dom/getDocument)) - (dom/createDom "script" (clj->js {}) amplitude-init-code)))) + (dom/createDom "script" nil amplitude-init-code)) + (go (let [user-id (-> js/browser + (.-runtime) + (.sendMessage (clj->js {:type "getUserId"})) + (promise->channel) + (js properties) + (fn [response-code response-body] + (go (>! res-channel {:code response-code + :body response-body}))))) + res-channel)) + ([event-name] (log-event event-name nil))) diff --git a/src/looped_in/background.cljs b/src/looped_in/background.cljs index dba1d1d..53f65af 100644 --- a/src/looped_in/background.cljs +++ b/src/looped_in/background.cljs @@ -1,6 +1,7 @@ (ns looped-in.background (:require [cljs.core.async :refer [go promise promise->channel]])) @@ -61,11 +62,30 @@ (.sendMessage (.-id tab) (clj->js {:type "openSidebar"})))) +(defn get-user-id [] + (go + (let [user-id (-> js/browser + (.-storage) + (.-local) + (.get "userId") + (promise->channel) + ( js/browser + (.-storage) + (.-local) + (.set (clj->js {"userId" uuid}))) + uuid) + user-id)))) + (defn handle-message [msg sender respond] (case (.-type msg) "hits" (channel->promise (go @hits)) "fetchItem" (channel->promise - (go (clj->js (js (promise (get-user-id)))) (-> js/browser (.-tabs) diff --git a/src/looped_in/sidebar.cljs b/src/looped_in/sidebar.cljs index 062500c..b782df1 100644 --- a/src/looped_in/sidebar.cljs +++ b/src/looped_in/sidebar.cljs @@ -102,7 +102,13 @@ "div" "storyHeader" (components/body30 (:title current-item)) - (components/item-link (:id current-item))) + (components/with-listener + (components/item-link (:id current-item)) + "click" + (fn [e] + (analytics/log-event + "CLICKED_HN_EXTERNAL_LINK" + {:type "story"})))) (components/story-caption (:points current-item) (:author current-item) (* (:created_at_i current-item) 1000))) @@ -113,7 +119,13 @@ (components/comment-caption (:author current-item) (* (:created_at_i current-item) 1000)) - (components/item-link (:id current-item))) + (components/with-listener + (components/item-link (:id current-item)) + "click" + (fn [e] + (analytics/log-event + "CLICKED_HN_EXTERNAL_LINK" + {:type "comment"})))) (components/comment-text (:text current-item)))) (map-indexed (fn [index child] (-> (components/card @@ -123,7 +135,13 @@ (components/comment-caption (:author child) (* (:created_at_i child) 1000)) - (components/item-link (:id child))) + (components/with-listener + (components/item-link (:id child)) + "click" + (fn [e] + (analytics/log-event + "CLICKED_HN_EXTERNAL_LINK" + {:type "comment"})))) (components/comment-text (:text child)) (-> (components/replies-indicator (count (:children child))) @@ -134,6 +152,9 @@ (components/with-listener "click" (fn [e] + (analytics/log-event + "CLICKED_HN_VIEW_COMMENTS" + {:depth (count (:depth state))}) (dispatch-message {:type :enq-depth :index index})))) @@ -158,7 +179,13 @@ "div" "storyHeader" (components/body30 (:title hit)) - (components/item-link (:objectID hit))) + (components/with-listener + (components/item-link (:objectID hit)) + "click" + (fn [e] + (analytics/log-event + "CLICKED_HN_EXTERNAL_LINK" + {:type "story"})))) (components/story-caption (:points hit) (:author hit) (* (:created_at_i hit) 1000)) @@ -170,6 +197,7 @@ (components/with-listener "click" (fn [e] + (analytics/log-event "CLICKED_HN_STORY") (dispatch-message {:type :loading :loading true}) (go (-> (fetch-item (:objectID hit)) @@ -197,19 +225,25 @@ (dom/append $container $sidebar-dom)))) (defn handle-close-button [e] - (.postMessage js/window.parent (clj->js {:type "closeSidebar"}) "*")) + (go (-> (analytics/log-event "CLOSED_SIDEBAR") + (js {:type "closeSidebar"}) "*")))))) (defn handle-events "Registers event listeners" [dispatch-message state] (events/listen (dom/getElement "closeSidebar") "click" handle-close-button) (when (not (nil? (dom/getElement "backButton"))) - (events/listen (dom/getElement "backButton") "click" (fn [e] - (let [depth (:depth state)] - (if (> (count depth) 0) - (dispatch-message {:type :deq-depth}) - (dispatch-message - {:type :clear-item}))))))) + (events/listen (dom/getElement "backButton") + "click" + (fn [e] + (analytics/log-event "CLICKED_BACK_BUTTON" {:depth (count (:depth state))}) + (let [depth (:depth state)] + (if (> (count depth) 0) + (dispatch-message {:type :deq-depth}) + (dispatch-message + {:type :clear-item}))))))) (defn run-render-loop "Runs the model-update-view loop" @@ -235,6 +269,7 @@ "Initializes the sidebar" [] (analytics/init-amplitude) + (analytics/log-event "OPENED_SIDEBAR") (let [initial-state (update-state {:type :loading :loading true} (model))] (run-render-loop initial-state) (go (-> (fetch-hits)