| @@ -7,6 +7,8 @@ | |||||
| jucerVersion="5.2.0"> | jucerVersion="5.2.0"> | ||||
| <MAINGROUP id="aOi9Tf" name="AnalyticsCollection"> | <MAINGROUP id="aOi9Tf" name="AnalyticsCollection"> | ||||
| <GROUP id="{527B2E17-B1B1-B919-CBEA-231058E23D74}" name="Source"> | <GROUP id="{527B2E17-B1B1-B919-CBEA-231058E23D74}" name="Source"> | ||||
| <FILE id="kkmpUZ" name="DemoAnalyticsEventTypes.h" compile="0" resource="0" | |||||
| file="Source/DemoAnalyticsEventTypes.h"/> | |||||
| <FILE id="qTLkDX" name="GoogleAnalyticsDestination.h" compile="0" resource="0" | <FILE id="qTLkDX" name="GoogleAnalyticsDestination.h" compile="0" resource="0" | ||||
| file="Source/GoogleAnalyticsDestination.h"/> | file="Source/GoogleAnalyticsDestination.h"/> | ||||
| <FILE id="DHs1bY" name="MainComponent.h" compile="0" resource="0" file="Source/MainComponent.h"/> | <FILE id="DHs1bY" name="MainComponent.h" compile="0" resource="0" file="Source/MainComponent.h"/> | ||||
| @@ -30,6 +30,7 @@ add_library( ${BINARY_NAME} | |||||
| SHARED | SHARED | ||||
| "../../../Source/DemoAnalyticsEventTypes.h" | |||||
| "../../../Source/GoogleAnalyticsDestination.h" | "../../../Source/GoogleAnalyticsDestination.h" | ||||
| "../../../Source/MainComponent.h" | "../../../Source/MainComponent.h" | ||||
| "../../../Source/Main.cpp" | "../../../Source/Main.cpp" | ||||
| @@ -788,6 +789,7 @@ add_library( ${BINARY_NAME} | |||||
| "../../../JuceLibraryCode/JuceHeader.h" | "../../../JuceLibraryCode/JuceHeader.h" | ||||
| ) | ) | ||||
| set_source_files_properties("../../../Source/DemoAnalyticsEventTypes.h" PROPERTIES HEADER_FILE_ONLY TRUE) | |||||
| set_source_files_properties("../../../Source/GoogleAnalyticsDestination.h" PROPERTIES HEADER_FILE_ONLY TRUE) | set_source_files_properties("../../../Source/GoogleAnalyticsDestination.h" PROPERTIES HEADER_FILE_ONLY TRUE) | ||||
| set_source_files_properties("../../../Source/MainComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE) | set_source_files_properties("../../../Source/MainComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE) | ||||
| set_source_files_properties("../../../../../modules/juce_analytics/analytics/juce_Analytics.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) | set_source_files_properties("../../../../../modules/juce_analytics/analytics/juce_Analytics.cpp" PROPERTIES HEADER_FILE_ONLY TRUE) | ||||
| @@ -38,12 +38,14 @@ | |||||
| 91208A06115D573563996967 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; }; | 91208A06115D573563996967 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; }; | ||||
| 996BEF5ADCE2EC85EB9F637F = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_data_structures"; path = "../../../../modules/juce_data_structures"; sourceTree = "SOURCE_ROOT"; }; | 996BEF5ADCE2EC85EB9F637F = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_data_structures"; path = "../../../../modules/juce_data_structures"; sourceTree = "SOURCE_ROOT"; }; | ||||
| A0DDFB3559C431E96EC59392 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_events.mm"; path = "../../JuceLibraryCode/include_juce_events.mm"; sourceTree = "SOURCE_ROOT"; }; | A0DDFB3559C431E96EC59392 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_events.mm"; path = "../../JuceLibraryCode/include_juce_events.mm"; sourceTree = "SOURCE_ROOT"; }; | ||||
| AAB5010326113C1358279789 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DemoAnalyticsEventTypes.h; path = ../../Source/DemoAnalyticsEventTypes.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| AD2CFF58DA5E1C6EDF9CC399 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_data_structures.mm"; path = "../../JuceLibraryCode/include_juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; }; | AD2CFF58DA5E1C6EDF9CC399 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_data_structures.mm"; path = "../../JuceLibraryCode/include_juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; }; | ||||
| C858CF44E96D416E4B6B9266 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; | C858CF44E96D416E4B6B9266 = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; | ||||
| D352CDB4CA7E8B21FAA83B8C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainComponent.h; path = ../../Source/MainComponent.h; sourceTree = "SOURCE_ROOT"; }; | D352CDB4CA7E8B21FAA83B8C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainComponent.h; path = ../../Source/MainComponent.h; sourceTree = "SOURCE_ROOT"; }; | ||||
| F2CF007AA4C90AC7A5AD1604 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_analytics"; path = "../../../../modules/juce_analytics"; sourceTree = "SOURCE_ROOT"; }; | F2CF007AA4C90AC7A5AD1604 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_analytics"; path = "../../../../modules/juce_analytics"; sourceTree = "SOURCE_ROOT"; }; | ||||
| FBCE051A0BA6C9FA3E64B47B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; | FBCE051A0BA6C9FA3E64B47B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; | ||||
| D269FA28B5D6012AEFE0BF20 = {isa = PBXGroup; children = ( | D269FA28B5D6012AEFE0BF20 = {isa = PBXGroup; children = ( | ||||
| AAB5010326113C1358279789, | |||||
| 8B927F72BA8726A064560942, | 8B927F72BA8726A064560942, | ||||
| D352CDB4CA7E8B21FAA83B8C, | D352CDB4CA7E8B21FAA83B8C, | ||||
| 6A86C9751E9DCFA62D4562DB, ); name = Source; sourceTree = "<group>"; }; | 6A86C9751E9DCFA62D4562DB, ); name = Source; sourceTree = "<group>"; }; | ||||
| @@ -1228,6 +1228,7 @@ | |||||
| <ClCompile Include="..\..\JuceLibraryCode\include_juce_gui_basics.cpp"/> | <ClCompile Include="..\..\JuceLibraryCode\include_juce_gui_basics.cpp"/> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <ClInclude Include="..\..\Source\DemoAnalyticsEventTypes.h"/> | |||||
| <ClInclude Include="..\..\Source\GoogleAnalyticsDestination.h"/> | <ClInclude Include="..\..\Source\GoogleAnalyticsDestination.h"/> | ||||
| <ClInclude Include="..\..\Source\MainComponent.h"/> | <ClInclude Include="..\..\Source\MainComponent.h"/> | ||||
| <ClInclude Include="..\..\..\..\modules\juce_analytics\analytics\juce_Analytics.h"/> | <ClInclude Include="..\..\..\..\modules\juce_analytics\analytics\juce_Analytics.h"/> | ||||
| @@ -1362,6 +1362,9 @@ | |||||
| </ClCompile> | </ClCompile> | ||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <ClInclude Include="..\..\Source\DemoAnalyticsEventTypes.h"> | |||||
| <Filter>AnalyticsCollection\Source</Filter> | |||||
| </ClInclude> | |||||
| <ClInclude Include="..\..\Source\GoogleAnalyticsDestination.h"> | <ClInclude Include="..\..\Source\GoogleAnalyticsDestination.h"> | ||||
| <Filter>AnalyticsCollection\Source</Filter> | <Filter>AnalyticsCollection\Source</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| @@ -42,6 +42,7 @@ | |||||
| 996BEF5ADCE2EC85EB9F637F = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_data_structures"; path = "../../../../modules/juce_data_structures"; sourceTree = "SOURCE_ROOT"; }; | 996BEF5ADCE2EC85EB9F637F = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_data_structures"; path = "../../../../modules/juce_data_structures"; sourceTree = "SOURCE_ROOT"; }; | ||||
| A0DDFB3559C431E96EC59392 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_events.mm"; path = "../../JuceLibraryCode/include_juce_events.mm"; sourceTree = "SOURCE_ROOT"; }; | A0DDFB3559C431E96EC59392 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_events.mm"; path = "../../JuceLibraryCode/include_juce_events.mm"; sourceTree = "SOURCE_ROOT"; }; | ||||
| A93F5541F6B3C067538499EF = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; | A93F5541F6B3C067538499EF = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; | ||||
| AAB5010326113C1358279789 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DemoAnalyticsEventTypes.h; path = ../../Source/DemoAnalyticsEventTypes.h; sourceTree = "SOURCE_ROOT"; }; | |||||
| AD2CFF58DA5E1C6EDF9CC399 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_data_structures.mm"; path = "../../JuceLibraryCode/include_juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; }; | AD2CFF58DA5E1C6EDF9CC399 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "include_juce_data_structures.mm"; path = "../../JuceLibraryCode/include_juce_data_structures.mm"; sourceTree = "SOURCE_ROOT"; }; | ||||
| BC02966C48A4F51E9A187E4A = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = AnalyticsCollection/Images.xcassets; sourceTree = "SOURCE_ROOT"; }; | BC02966C48A4F51E9A187E4A = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = AnalyticsCollection/Images.xcassets; sourceTree = "SOURCE_ROOT"; }; | ||||
| D352CDB4CA7E8B21FAA83B8C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainComponent.h; path = ../../Source/MainComponent.h; sourceTree = "SOURCE_ROOT"; }; | D352CDB4CA7E8B21FAA83B8C = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MainComponent.h; path = ../../Source/MainComponent.h; sourceTree = "SOURCE_ROOT"; }; | ||||
| @@ -50,6 +51,7 @@ | |||||
| F2CF007AA4C90AC7A5AD1604 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_analytics"; path = "../../../../modules/juce_analytics"; sourceTree = "SOURCE_ROOT"; }; | F2CF007AA4C90AC7A5AD1604 = {isa = PBXFileReference; lastKnownFileType = file; name = "juce_analytics"; path = "../../../../modules/juce_analytics"; sourceTree = "SOURCE_ROOT"; }; | ||||
| FBCE051A0BA6C9FA3E64B47B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; | FBCE051A0BA6C9FA3E64B47B = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; | ||||
| D269FA28B5D6012AEFE0BF20 = {isa = PBXGroup; children = ( | D269FA28B5D6012AEFE0BF20 = {isa = PBXGroup; children = ( | ||||
| AAB5010326113C1358279789, | |||||
| 8B927F72BA8726A064560942, | 8B927F72BA8726A064560942, | ||||
| D352CDB4CA7E8B21FAA83B8C, | D352CDB4CA7E8B21FAA83B8C, | ||||
| 6A86C9751E9DCFA62D4562DB, ); name = Source; sourceTree = "<group>"; }; | 6A86C9751E9DCFA62D4562DB, ); name = Source; sourceTree = "<group>"; }; | ||||
| @@ -0,0 +1,10 @@ | |||||
| #pragma once | |||||
| enum DemoAnalyticsEventTypes | |||||
| { | |||||
| event, | |||||
| sessionStart, | |||||
| sessionEnd, | |||||
| screenView, | |||||
| exception | |||||
| }; | |||||
| @@ -1,5 +1,7 @@ | |||||
| #include "../JuceLibraryCode/JuceHeader.h" | #include "../JuceLibraryCode/JuceHeader.h" | ||||
| #include "DemoAnalyticsEventTypes.h" | |||||
| class GoogleAnalyticsDestination : public ThreadedAnalyticsDestination | class GoogleAnalyticsDestination : public ThreadedAnalyticsDestination | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -47,32 +49,56 @@ public: | |||||
| { | { | ||||
| // Send events to Google Analytics. | // Send events to Google Analytics. | ||||
| String appData ("v=1&tid=" + apiKey + "&t=event&"); | |||||
| String appData ("v=1&aip=1&tid=" + apiKey); | |||||
| StringArray postData; | StringArray postData; | ||||
| for (auto& event : events) | for (auto& event : events) | ||||
| { | { | ||||
| StringPairArray data; | StringPairArray data; | ||||
| if (event.name == "startup") | |||||
| { | |||||
| data.set ("ec", "info"); | |||||
| data.set ("ea", "appStarted"); | |||||
| } | |||||
| else if (event.name == "shutdown") | |||||
| { | |||||
| data.set ("ec", "info"); | |||||
| data.set ("ea", "appStopped"); | |||||
| } | |||||
| else if (event.name == "button_press") | |||||
| { | |||||
| data.set ("ec", "button_press"); | |||||
| data.set ("ea", event.parameters["id"]); | |||||
| } | |||||
| else | |||||
| switch (event.eventType) | |||||
| { | { | ||||
| continue; | |||||
| case (DemoAnalyticsEventTypes::event): | |||||
| { | |||||
| data.set ("t", "event"); | |||||
| if (event.name == "startup") | |||||
| { | |||||
| data.set ("ec", "info"); | |||||
| data.set ("ea", "appStarted"); | |||||
| } | |||||
| else if (event.name == "shutdown") | |||||
| { | |||||
| data.set ("ec", "info"); | |||||
| data.set ("ea", "appStopped"); | |||||
| } | |||||
| else if (event.name == "button_press") | |||||
| { | |||||
| data.set ("ec", "button_press"); | |||||
| data.set ("ea", event.parameters["id"]); | |||||
| } | |||||
| else if (event.name == "crash") | |||||
| { | |||||
| data.set ("ec", "crash"); | |||||
| data.set ("ea", "crash"); | |||||
| } | |||||
| else | |||||
| { | |||||
| jassertfalse; | |||||
| continue; | |||||
| } | |||||
| break; | |||||
| } | |||||
| default: | |||||
| { | |||||
| // Unknown event type! In this demo app we're just using a | |||||
| // single event type, but in a real app you probably want to | |||||
| // handle multiple ones. | |||||
| jassertfalse; | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| data.set ("cid", event.userID); | data.set ("cid", event.userID); | ||||
| @@ -82,7 +108,7 @@ public: | |||||
| for (auto& key : data.getAllKeys()) | for (auto& key : data.getAllKeys()) | ||||
| eventData.add (key + "=" + URL::addEscapeChars (data[key], true)); | eventData.add (key + "=" + URL::addEscapeChars (data[key], true)); | ||||
| postData.add (appData + eventData.joinIntoString ("&")); | |||||
| postData.add (appData + "&" + eventData.joinIntoString ("&")); | |||||
| } | } | ||||
| auto url = URL ("https://www.google-analytics.com/batch") | auto url = URL ("https://www.google-analytics.com/batch") | ||||
| @@ -139,6 +165,7 @@ private: | |||||
| { | { | ||||
| auto* xmlEvent = new XmlElement ("google_analytics_event"); | auto* xmlEvent = new XmlElement ("google_analytics_event"); | ||||
| xmlEvent->setAttribute ("name", event.name); | xmlEvent->setAttribute ("name", event.name); | ||||
| xmlEvent->setAttribute ("type", event.eventType); | |||||
| xmlEvent->setAttribute ("timestamp", (int) event.timestamp); | xmlEvent->setAttribute ("timestamp", (int) event.timestamp); | ||||
| xmlEvent->setAttribute ("user_id", event.userID); | xmlEvent->setAttribute ("user_id", event.userID); | ||||
| @@ -194,6 +221,7 @@ private: | |||||
| restoredEventQueue.push_back ({ | restoredEventQueue.push_back ({ | ||||
| xmlEvent->getStringAttribute ("name"), | xmlEvent->getStringAttribute ("name"), | ||||
| xmlEvent->getIntAttribute ("type"), | |||||
| (uint32) xmlEvent->getIntAttribute ("timestamp"), | (uint32) xmlEvent->getIntAttribute ("timestamp"), | ||||
| parameters, | parameters, | ||||
| xmlEvent->getStringAttribute ("user_id"), | xmlEvent->getStringAttribute ("user_id"), | ||||
| @@ -2,6 +2,7 @@ | |||||
| #include "GoogleAnalyticsDestination.h" | #include "GoogleAnalyticsDestination.h" | ||||
| #include "MainComponent.h" | #include "MainComponent.h" | ||||
| #include "DemoAnalyticsEventTypes.h" | |||||
| //============================================================================== | //============================================================================== | ||||
| class AnalyticsCollectionApplication : public JUCEApplication | class AnalyticsCollectionApplication : public JUCEApplication | ||||
| @@ -17,8 +18,8 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| void initialise (const String&) override | void initialise (const String&) override | ||||
| { | { | ||||
| // Add an analytics identifier for the user. Make sure you don't collect | |||||
| // identifiable information accidentally if you haven't asked for permission! | |||||
| // Add an analytics identifier for the user. Make sure you don't accidentally | |||||
| // collect identifiable information if you haven't asked for permission! | |||||
| Analytics::getInstance()->setUserId ("AnonUser1234"); | Analytics::getInstance()->setUserId ("AnonUser1234"); | ||||
| // Add any other constant user information. | // Add any other constant user information. | ||||
| @@ -29,14 +30,18 @@ public: | |||||
| // Add any analytics destinations we want to use to the Analytics singleton. | // Add any analytics destinations we want to use to the Analytics singleton. | ||||
| Analytics::getInstance()->addDestination (new GoogleAnalyticsDestination()); | Analytics::getInstance()->addDestination (new GoogleAnalyticsDestination()); | ||||
| Analytics::getInstance()->logEvent ("startup", {}); | |||||
| // The event type here should probably be DemoAnalyticsEventTypes::sessionStart | |||||
| // in a more advanced app. | |||||
| Analytics::getInstance()->logEvent ("startup", {}, DemoAnalyticsEventTypes::event); | |||||
| mainWindow = new MainWindow (getApplicationName()); | mainWindow = new MainWindow (getApplicationName()); | ||||
| } | } | ||||
| void shutdown() override | void shutdown() override | ||||
| { | { | ||||
| Analytics::getInstance()->logEvent ("shutdown", {}); | |||||
| // The event type here should probably be DemoAnalyticsEventTypes::sessionEnd | |||||
| // in a more advanced app. | |||||
| Analytics::getInstance()->logEvent ("shutdown", {}, DemoAnalyticsEventTypes::event); | |||||
| // Add your application's shutdown code here.. | // Add your application's shutdown code here.. | ||||
| @@ -2,13 +2,19 @@ | |||||
| #include "../JuceLibraryCode/JuceHeader.h" | #include "../JuceLibraryCode/JuceHeader.h" | ||||
| class MainContentComponent : public Component | |||||
| #include "DemoAnalyticsEventTypes.h" | |||||
| class MainContentComponent : public Component, | |||||
| private Button::Listener | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| MainContentComponent() | MainContentComponent() | ||||
| { | { | ||||
| crashButton.addListener (this); | |||||
| addAndMakeVisible (eventButton); | addAndMakeVisible (eventButton); | ||||
| addAndMakeVisible (crashButton); | |||||
| setSize (300, 200); | setSize (300, 200); | ||||
| @@ -17,7 +23,10 @@ public: | |||||
| logEventButtonPress = new ButtonTracker (eventButton, "button_press", logButtonPressParameters); | logEventButtonPress = new ButtonTracker (eventButton, "button_press", logButtonPressParameters); | ||||
| } | } | ||||
| ~MainContentComponent() {} | |||||
| ~MainContentComponent() | |||||
| { | |||||
| crashButton.removeListener (this); | |||||
| } | |||||
| void paint (Graphics& g) override | void paint (Graphics& g) override | ||||
| { | { | ||||
| @@ -26,12 +35,23 @@ public: | |||||
| void resized() override | void resized() override | ||||
| { | { | ||||
| eventButton.centreWithSize (100, 50); | |||||
| eventButton.centreWithSize (100, 40); | |||||
| eventButton.setBounds (eventButton.getBounds().translated (0, 25)); | |||||
| crashButton.setBounds (eventButton.getBounds().translated (0, -50)); | |||||
| } | } | ||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| TextButton eventButton { "Press me!" }; | |||||
| void buttonClicked (Button*) override | |||||
| { | |||||
| // In a more advanced application you would probably use a different event | |||||
| // type here. | |||||
| Analytics::getInstance()->logEvent ("crash", {}, DemoAnalyticsEventTypes::event); | |||||
| Analytics::getInstance()->getDestinations().clear(); | |||||
| JUCEApplication::getInstance()->shutdown(); | |||||
| } | |||||
| TextButton eventButton { "Press me!" }, crashButton { "Simulate crash!" }; | |||||
| ScopedPointer<ButtonTracker> logEventButtonPress; | ScopedPointer<ButtonTracker> logEventButtonPress; | ||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent) | ||||
| @@ -28,6 +28,11 @@ void Analytics::addDestination (AnalyticsDestination* destination) | |||||
| destinations.add (destination); | destinations.add (destination); | ||||
| } | } | ||||
| OwnedArray<AnalyticsDestination>& Analytics::getDestinations() | |||||
| { | |||||
| return destinations; | |||||
| } | |||||
| void Analytics::setUserId (const String& newUserId) | void Analytics::setUserId (const String& newUserId) | ||||
| { | { | ||||
| userId = newUserId; | userId = newUserId; | ||||
| @@ -39,13 +44,15 @@ void Analytics::setUserProperties (const StringPairArray& properties) | |||||
| } | } | ||||
| void Analytics::logEvent (const String& eventName, | void Analytics::logEvent (const String& eventName, | ||||
| const StringPairArray& parameters) | |||||
| const StringPairArray& parameters, | |||||
| int eventType) | |||||
| { | { | ||||
| if (! isSuspended) | if (! isSuspended) | ||||
| { | { | ||||
| AnalyticsDestination::AnalyticsEvent event | AnalyticsDestination::AnalyticsEvent event | ||||
| { | { | ||||
| eventName, | eventName, | ||||
| eventType, | |||||
| Time::getMillisecondCounter(), | Time::getMillisecondCounter(), | ||||
| parameters, | parameters, | ||||
| userId, | userId, | ||||
| @@ -47,6 +47,14 @@ public: | |||||
| */ | */ | ||||
| void addDestination (AnalyticsDestination* destination); | void addDestination (AnalyticsDestination* destination); | ||||
| /** Returns the array of AnalyticsDestinations managed by this class. | |||||
| If you have added any subclasses of ThreadedAnalyticsDestination to | |||||
| this class then you can remove them from this list to force them to | |||||
| flush any pending events. | |||||
| */ | |||||
| OwnedArray<AnalyticsDestination>& getDestinations(); | |||||
| /** Sets a user ID that will be added to all AnalyticsEvents sent to | /** Sets a user ID that will be added to all AnalyticsEvents sent to | ||||
| AnalyticsDestinations. | AnalyticsDestinations. | ||||
| @@ -65,15 +73,17 @@ public: | |||||
| The AnalyticsEvent will be timestamped, and will have the userId and | The AnalyticsEvent will be timestamped, and will have the userId and | ||||
| userProperties populated by values previously set by calls to | userProperties populated by values previously set by calls to | ||||
| setUserId and setUserProperties. The name and parameters will be | |||||
| setUserId and setUserProperties. The name, parameters and type will be | |||||
| populated by the arguments supplied to this function. | populated by the arguments supplied to this function. | ||||
| @param eventName the event name | @param eventName the event name | ||||
| @param parameters the event parameters | @param parameters the event parameters | ||||
| @param eventType (optional) an integer to indicate the event | |||||
| type, which will be set to 0 if not supplied. | |||||
| */ | */ | ||||
| void logEvent (const String& eventName, const StringPairArray& parameters); | |||||
| void logEvent (const String& eventName, const StringPairArray& parameters, int eventType = 0); | |||||
| /** Suspends analytics submission to AnalyticsDestinations. | |||||
| /** Suspends analytics submissions to AnalyticsDestinations. | |||||
| @param shouldBeSuspended if event submission should be suspended | @param shouldBeSuspended if event submission should be suspended | ||||
| */ | */ | ||||
| @@ -25,10 +25,12 @@ namespace juce | |||||
| ButtonTracker::ButtonTracker (Button& buttonToTrack, | ButtonTracker::ButtonTracker (Button& buttonToTrack, | ||||
| const String& triggeredEventName, | const String& triggeredEventName, | ||||
| const StringPairArray& triggeredEventParameters) | |||||
| const StringPairArray& triggeredEventParameters, | |||||
| int triggeredEventType) | |||||
| : button (buttonToTrack), | : button (buttonToTrack), | ||||
| eventName (triggeredEventName), | eventName (triggeredEventName), | ||||
| eventParameters (triggeredEventParameters) | |||||
| eventParameters (triggeredEventParameters), | |||||
| eventType (triggeredEventType) | |||||
| { | { | ||||
| button.addListener (this); | button.addListener (this); | ||||
| } | } | ||||
| @@ -47,7 +49,7 @@ void ButtonTracker::buttonClicked (Button* b) | |||||
| if (button.getClickingTogglesState()) | if (button.getClickingTogglesState()) | ||||
| params.set ("ButtonState", button.getToggleState() ? "On" : "Off"); | params.set ("ButtonState", button.getToggleState() ? "On" : "Off"); | ||||
| Analytics::getInstance()->logEvent (eventName, params); | |||||
| Analytics::getInstance()->logEvent (eventName, params, eventType); | |||||
| } | } | ||||
| } | } | ||||
| @@ -51,7 +51,8 @@ public: | |||||
| */ | */ | ||||
| ButtonTracker (Button& buttonToTrack, | ButtonTracker (Button& buttonToTrack, | ||||
| const String& triggeredEventName, | const String& triggeredEventName, | ||||
| const StringPairArray& triggeredEventParameters = {}); | |||||
| const StringPairArray& triggeredEventParameters = {}, | |||||
| int triggeredEventType = 0); | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~ButtonTracker(); | ~ButtonTracker(); | ||||
| @@ -63,6 +64,7 @@ private: | |||||
| Button& button; | Button& button; | ||||
| const String eventName; | const String eventName; | ||||
| const StringPairArray eventParameters; | const StringPairArray eventParameters; | ||||
| const int eventType; | |||||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonTracker) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonTracker) | ||||
| }; | }; | ||||
| @@ -44,6 +44,12 @@ struct JUCE_API AnalyticsDestination | |||||
| /** The name of the event. */ | /** The name of the event. */ | ||||
| String name; | String name; | ||||
| /** An optional integer representing the type of the event. You can use | |||||
| this to indicate if the event was a screenview, session start, | |||||
| exception, etc. | |||||
| */ | |||||
| int eventType; | |||||
| /** | /** | ||||
| The timestamp of the event. | The timestamp of the event. | ||||
| @@ -297,7 +297,7 @@ struct ThreadedAnalyticsDestinationTests : public UnitTest | |||||
| std::deque<AnalyticsDestination::AnalyticsEvent> testEvents; | std::deque<AnalyticsDestination::AnalyticsEvent> testEvents; | ||||
| for (int i = 0; i < 7; ++i) | for (int i = 0; i < 7; ++i) | ||||
| testEvents.push_back ({ String (i), Time::getMillisecondCounter(), {}, "TestUser", {} }); | |||||
| testEvents.push_back ({ String (i), 0, Time::getMillisecondCounter(), {}, "TestUser", {} }); | |||||
| std::deque<AnalyticsDestination::AnalyticsEvent> loggedEvents, unloggedEvents; | std::deque<AnalyticsDestination::AnalyticsEvent> loggedEvents, unloggedEvents; | ||||
| @@ -169,6 +169,7 @@ JUCESplashScreen::JUCESplashScreen (Component& parent) | |||||
| StringPairArray data; | StringPairArray data; | ||||
| data.set ("v", "1"); | data.set ("v", "1"); | ||||
| data.set ("aip", "1"); | |||||
| data.set ("tid", "UA-19759318-3"); | data.set ("tid", "UA-19759318-3"); | ||||
| data.set ("cid", deviceIdentifier); | data.set ("cid", deviceIdentifier); | ||||
| data.set ("t", "event"); | data.set ("t", "event"); | ||||