@@ -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"); | ||||