Browse Source

Improvements to the Analytics class

tags/2021-05-28
Tom Poole 7 years ago
parent
commit
beec82b8cb
17 changed files with 140 additions and 37 deletions
  1. +2
    -0
      examples/AnalyticsCollection/AnalyticsCollection.jucer
  2. +2
    -0
      examples/AnalyticsCollection/Builds/Android/app/CMakeLists.txt
  3. +2
    -0
      examples/AnalyticsCollection/Builds/MacOSX/AnalyticsCollection.xcodeproj/project.pbxproj
  4. +1
    -0
      examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj
  5. +3
    -0
      examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj.filters
  6. +2
    -0
      examples/AnalyticsCollection/Builds/iOS/AnalyticsCollection.xcodeproj/project.pbxproj
  7. +10
    -0
      examples/AnalyticsCollection/Source/DemoAnalyticsEventTypes.h
  8. +48
    -20
      examples/AnalyticsCollection/Source/GoogleAnalyticsDestination.h
  9. +9
    -4
      examples/AnalyticsCollection/Source/Main.cpp
  10. +24
    -4
      examples/AnalyticsCollection/Source/MainComponent.h
  11. +8
    -1
      modules/juce_analytics/analytics/juce_Analytics.cpp
  12. +13
    -3
      modules/juce_analytics/analytics/juce_Analytics.h
  13. +5
    -3
      modules/juce_analytics/analytics/juce_ButtonTracker.cpp
  14. +3
    -1
      modules/juce_analytics/analytics/juce_ButtonTracker.h
  15. +6
    -0
      modules/juce_analytics/destinations/juce_AnalyticsDestination.h
  16. +1
    -1
      modules/juce_analytics/destinations/juce_ThreadedAnalyticsDestination.cpp
  17. +1
    -0
      modules/juce_gui_basics/misc/juce_JUCESplashScreen.cpp

+ 2
- 0
examples/AnalyticsCollection/AnalyticsCollection.jucer View File

@@ -7,6 +7,8 @@
jucerVersion="5.2.0">
<MAINGROUP id="aOi9Tf" name="AnalyticsCollection">
<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="Source/GoogleAnalyticsDestination.h"/>
<FILE id="DHs1bY" name="MainComponent.h" compile="0" resource="0" file="Source/MainComponent.h"/>


+ 2
- 0
examples/AnalyticsCollection/Builds/Android/app/CMakeLists.txt View File

@@ -30,6 +30,7 @@ add_library( ${BINARY_NAME}
SHARED
"../../../Source/DemoAnalyticsEventTypes.h"
"../../../Source/GoogleAnalyticsDestination.h"
"../../../Source/MainComponent.h"
"../../../Source/Main.cpp"
@@ -788,6 +789,7 @@ add_library( ${BINARY_NAME}
"../../../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/MainComponent.h" PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties("../../../../../modules/juce_analytics/analytics/juce_Analytics.cpp" PROPERTIES HEADER_FILE_ONLY TRUE)


+ 2
- 0
examples/AnalyticsCollection/Builds/MacOSX/AnalyticsCollection.xcodeproj/project.pbxproj View File

@@ -38,12 +38,14 @@
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"; };
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"; };
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"; };
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; };
D269FA28B5D6012AEFE0BF20 = {isa = PBXGroup; children = (
AAB5010326113C1358279789,
8B927F72BA8726A064560942,
D352CDB4CA7E8B21FAA83B8C,
6A86C9751E9DCFA62D4562DB, ); name = Source; sourceTree = "<group>"; };


+ 1
- 0
examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj View File

@@ -1228,6 +1228,7 @@
<ClCompile Include="..\..\JuceLibraryCode\include_juce_gui_basics.cpp"/>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Source\DemoAnalyticsEventTypes.h"/>
<ClInclude Include="..\..\Source\GoogleAnalyticsDestination.h"/>
<ClInclude Include="..\..\Source\MainComponent.h"/>
<ClInclude Include="..\..\..\..\modules\juce_analytics\analytics\juce_Analytics.h"/>


+ 3
- 0
examples/AnalyticsCollection/Builds/VisualStudio2017/AnalyticsCollection_App.vcxproj.filters View File

@@ -1362,6 +1362,9 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Source\DemoAnalyticsEventTypes.h">
<Filter>AnalyticsCollection\Source</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\GoogleAnalyticsDestination.h">
<Filter>AnalyticsCollection\Source</Filter>
</ClInclude>


+ 2
- 0
examples/AnalyticsCollection/Builds/iOS/AnalyticsCollection.xcodeproj/project.pbxproj View File

@@ -42,6 +42,7 @@
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"; };
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"; };
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"; };
@@ -50,6 +51,7 @@
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; };
D269FA28B5D6012AEFE0BF20 = {isa = PBXGroup; children = (
AAB5010326113C1358279789,
8B927F72BA8726A064560942,
D352CDB4CA7E8B21FAA83B8C,
6A86C9751E9DCFA62D4562DB, ); name = Source; sourceTree = "<group>"; };


+ 10
- 0
examples/AnalyticsCollection/Source/DemoAnalyticsEventTypes.h View File

@@ -0,0 +1,10 @@
#pragma once
enum DemoAnalyticsEventTypes
{
event,
sessionStart,
sessionEnd,
screenView,
exception
};

+ 48
- 20
examples/AnalyticsCollection/Source/GoogleAnalyticsDestination.h View File

@@ -1,5 +1,7 @@
#include "../JuceLibraryCode/JuceHeader.h"
#include "DemoAnalyticsEventTypes.h"
class GoogleAnalyticsDestination : public ThreadedAnalyticsDestination
{
public:
@@ -47,32 +49,56 @@ public:
{
// Send events to Google Analytics.
String appData ("v=1&tid=" + apiKey + "&t=event&");
String appData ("v=1&aip=1&tid=" + apiKey);
StringArray postData;
for (auto& event : events)
{
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);
@@ -82,7 +108,7 @@ public:
for (auto& key : data.getAllKeys())
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")
@@ -139,6 +165,7 @@ private:
{
auto* xmlEvent = new XmlElement ("google_analytics_event");
xmlEvent->setAttribute ("name", event.name);
xmlEvent->setAttribute ("type", event.eventType);
xmlEvent->setAttribute ("timestamp", (int) event.timestamp);
xmlEvent->setAttribute ("user_id", event.userID);
@@ -194,6 +221,7 @@ private:
restoredEventQueue.push_back ({
xmlEvent->getStringAttribute ("name"),
xmlEvent->getIntAttribute ("type"),
(uint32) xmlEvent->getIntAttribute ("timestamp"),
parameters,
xmlEvent->getStringAttribute ("user_id"),


+ 9
- 4
examples/AnalyticsCollection/Source/Main.cpp View File

@@ -2,6 +2,7 @@
#include "GoogleAnalyticsDestination.h"
#include "MainComponent.h"
#include "DemoAnalyticsEventTypes.h"
//==============================================================================
class AnalyticsCollectionApplication : public JUCEApplication
@@ -17,8 +18,8 @@ public:
//==============================================================================
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");
// Add any other constant user information.
@@ -29,14 +30,18 @@ public:
// Add any analytics destinations we want to use to the Analytics singleton.
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());
}
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..


+ 24
- 4
examples/AnalyticsCollection/Source/MainComponent.h View File

@@ -2,13 +2,19 @@
#include "../JuceLibraryCode/JuceHeader.h"
class MainContentComponent : public Component
#include "DemoAnalyticsEventTypes.h"
class MainContentComponent : public Component,
private Button::Listener
{
public:
//==============================================================================
MainContentComponent()
{
crashButton.addListener (this);
addAndMakeVisible (eventButton);
addAndMakeVisible (crashButton);
setSize (300, 200);
@@ -17,7 +23,10 @@ public:
logEventButtonPress = new ButtonTracker (eventButton, "button_press", logButtonPressParameters);
}
~MainContentComponent() {}
~MainContentComponent()
{
crashButton.removeListener (this);
}
void paint (Graphics& g) override
{
@@ -26,12 +35,23 @@ public:
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:
//==============================================================================
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;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)


+ 8
- 1
modules/juce_analytics/analytics/juce_Analytics.cpp View File

@@ -28,6 +28,11 @@ void Analytics::addDestination (AnalyticsDestination* destination)
destinations.add (destination);
}
OwnedArray<AnalyticsDestination>& Analytics::getDestinations()
{
return destinations;
}
void Analytics::setUserId (const String& newUserId)
{
userId = newUserId;
@@ -39,13 +44,15 @@ void Analytics::setUserProperties (const StringPairArray& properties)
}
void Analytics::logEvent (const String& eventName,
const StringPairArray& parameters)
const StringPairArray& parameters,
int eventType)
{
if (! isSuspended)
{
AnalyticsDestination::AnalyticsEvent event
{
eventName,
eventType,
Time::getMillisecondCounter(),
parameters,
userId,


+ 13
- 3
modules/juce_analytics/analytics/juce_Analytics.h View File

@@ -47,6 +47,14 @@ public:
*/
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
AnalyticsDestinations.
@@ -65,15 +73,17 @@ public:
The AnalyticsEvent will be timestamped, and will have the userId and
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.
@param eventName the event name
@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
*/


+ 5
- 3
modules/juce_analytics/analytics/juce_ButtonTracker.cpp View File

@@ -25,10 +25,12 @@ namespace juce
ButtonTracker::ButtonTracker (Button& buttonToTrack,
const String& triggeredEventName,
const StringPairArray& triggeredEventParameters)
const StringPairArray& triggeredEventParameters,
int triggeredEventType)
: button (buttonToTrack),
eventName (triggeredEventName),
eventParameters (triggeredEventParameters)
eventParameters (triggeredEventParameters),
eventType (triggeredEventType)
{
button.addListener (this);
}
@@ -47,7 +49,7 @@ void ButtonTracker::buttonClicked (Button* b)
if (button.getClickingTogglesState())
params.set ("ButtonState", button.getToggleState() ? "On" : "Off");
Analytics::getInstance()->logEvent (eventName, params);
Analytics::getInstance()->logEvent (eventName, params, eventType);
}
}


+ 3
- 1
modules/juce_analytics/analytics/juce_ButtonTracker.h View File

@@ -51,7 +51,8 @@ public:
*/
ButtonTracker (Button& buttonToTrack,
const String& triggeredEventName,
const StringPairArray& triggeredEventParameters = {});
const StringPairArray& triggeredEventParameters = {},
int triggeredEventType = 0);
/** Destructor. */
~ButtonTracker();
@@ -63,6 +64,7 @@ private:
Button& button;
const String eventName;
const StringPairArray eventParameters;
const int eventType;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ButtonTracker)
};


+ 6
- 0
modules/juce_analytics/destinations/juce_AnalyticsDestination.h View File

@@ -44,6 +44,12 @@ struct JUCE_API AnalyticsDestination
/** The name of the event. */
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.


+ 1
- 1
modules/juce_analytics/destinations/juce_ThreadedAnalyticsDestination.cpp View File

@@ -297,7 +297,7 @@ struct ThreadedAnalyticsDestinationTests : public UnitTest
std::deque<AnalyticsDestination::AnalyticsEvent> testEvents;
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;


+ 1
- 0
modules/juce_gui_basics/misc/juce_JUCESplashScreen.cpp View File

@@ -169,6 +169,7 @@ JUCESplashScreen::JUCESplashScreen (Component& parent)
StringPairArray data;
data.set ("v", "1");
data.set ("aip", "1");
data.set ("tid", "UA-19759318-3");
data.set ("cid", deviceIdentifier);
data.set ("t", "event");


Loading…
Cancel
Save