Is Analytics.CustomEvent supposed to work?

I’ve created a custom event called “funnel”, with a parameter “funnelStep” of type string in the dashboard Event Manager and also have enabled it.

Code for sending the event is like so:

var pars = new Dictionary<string, object>();
        pars["funnelStep"] = name;

        Analytics.CustomEvent("funnel", pars);

However, in my testing I just see standard events, no custom event… googling this reveals numerous similar complaints. However it is not clear to me if I should be using AnalyticsEvent.Custom instead since documentation hints at either.

Hi, both Analytics.CustomEvent and AnalyticsEvent.Custom should work the same, but it’s worth trying AnalyticsEvent.Custom.

In addition, there are 2 other ways to confirm if you are sending Analytics Events:

  1. Surround your Analytics.CustomEvent with a Debug.Log, like this: Debug.Log(Analytics.CustomEvent());
    This should print “Ok” in the console if the events are sent. Otherwise, it will give you an error message.
    https://docs.unity3d.com/ScriptReference/Analytics.AnalyticsResult.html

  2. Use a network traffic analyzer, such as Charles Proxy:
    https://www.charlesproxy.com/
    https://support.unity3d.com/hc/en-us/articles/115002917683-Using-Charles-Proxy-with-Unity

I hope this helps. If the problem persists, please email “analytics-support@unity3d.com” to create a Zendesk ticket, please provide the project ID so we can check it.

Already debugged stepped through yesterday to verify the events were indeed being sent. Could have a look at actual network communication as the next step, but TBH I might switch to Firebase before then.

Thanks, please feel free to contact us if you encounter any problems.

Ok, Analytics.CustomEvent does show up… in the legacy analytics view.

What steps do I need to take for it to show up in the beta view? Checking the obvious: I would assume I am using the beta since other information (including standard events) shows up on the Beta header in the dashboard. If there is a way to prove/disprove (e.g. by stating a required com.unity.analytics package version), let me know.

This kind of illustrates my ongoing headache. I specially looked for a beta API for custom events, but ended up routing to legacy analytics. I have no idea if there’s any way to actually do custom events in the beta.

Hi Petter,

Thanks for your feedback. It has been noted and passed on to the teams.
The code that you shared seems to be for legacy analytics.
you can go to the following link to gain access to the analytics beta documentation.
Here is a summary of the steps needed to send a custom event to the sdk with a simple example (required Unity 2019.4 and up)

  • Sign up for the beta if you haven’t already

  • Download and install the following packages. These can be added directly to your projects PACKAGES folder. open the manifest.json file. Append the following to the dependencies
    “com.unity.services.analytics”: “2.0.7-pre.7”,
    “com.unity.services.authentication”: “1.0.0-pre.4”

  • Your project will now have the packages required for analytics beta.

  • Link your project to the dashboard by going to EDIT > PROJECT SETTINGS

  • Click on Services and link your project

  • Create a custom event by going to your dashboard then ANALYTICS > EVENT MANAGER

  • Add a new event called “funnel” by clicking add new event

  • Assign a parameter > Click on add new parameter

  • Once your new event and parameter are created activate the event

  • Your event is now created in analytics beta. Head back in the editor

  • Create a new game object called UGS_Analytics (Any name can be given here)

  • Create a new script attached to the game object.

  • Add the following code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Services.Analytics;
using Unity.Services.Core;
using Unity.Services.Authentication;

public class UGS_Analytics : MonoBehaviour
{
    async void Start()
    {

        await UnityServices.InitializeAsync();
     
        if (!AuthenticationService.Instance.IsSignedIn)
        {
            await AuthenticationService.Instance.SignInAnonymouslyAsync();
        }

        HandleCustomEvent();
    }

    private void HandleCustomEvent()
    {
        //Handle Custom event
        Dictionary<string, object> parameters = new Dictionary<string, object>()
        {
            { "funnelStep", "Step 1"}
        };
        
        Events.CustomData("funnel", parameters);
        // You can call Events.Flush() to send the event immediately
        Events.Flush();
    }
}

This code will send an event called “funnel” with parameter “funnelStep” and value “Step 1”
to the analytics beta.

Let me know if this helps or have additional questions.

4 Likes

Thanks for the very detailed explanation SebT, it’s more than I could have hoped for! At the very least my packages and calls are off it appears. Will fix, now it feels 100% certain what went wrong.

1 Like

I’m trying to make these Custom Events as well as you described SebT, but I just can’t see the Custom Events.
I installed the Authentication package, but using Unity.Services.Authentication gives an error.
7754112--975903--upload_2021-12-21_23-34-55.png

I keep getting this in my Console. I can see Standard Events fine, but my custom event is not showing up.
7754112--975900--upload_2021-12-21_23-33-49.png

Hi Lucian, thanks for reaching out! When you hover your mouse over the error in Authentication, what does it say? Did you download and install the package for Authentication for the project in question?

Also, for your error in your console, when you double click on it, it should bring you to where the error is being generated in your code. Can you share a screenshot of that as well, or if you already know, share the code that is causing the error?

Thanks!
Randy

Hi Randy.
The Authentication is not giving the error anymore today. Looks like I just had to restart Unity.
But it is still giving me the same console errors for the events not being uploaded.
They bring me to the UploadComplete function here in the Dispatcher.cs when I click on them. I’m not sure what JSON I’m supposed to go and check.

public void Flush()
        {
            // There is still a request pending.
            if (m_Request != null)
            {
                return;
            }

            FlushBufferToService();
        }

        void FlushBufferToService()
        {
            // Serialize it into a JSON Blob, then POST it to the Collect bulk URL.
            // 'Bulk Events' -> https://docs.deltadna.com/advanced-integration/rest-api/

            (string collectData, int sentTokens) = m_DataBuffer.Serialize();

            if (string.IsNullOrEmpty(collectData))
            {
                return;
            }

            byte[] postBytes = Encoding.UTF8.GetBytes(collectData);
          
            UnityWebRequest request = new UnityWebRequest(CollectUrl, UnityWebRequest.kHttpVerbPOST);
            UploadHandlerRaw upload = new UploadHandlerRaw(postBytes);
            upload.contentType = "application/json";
            request.uploadHandler = upload;

            m_RequestSentTokens = sentTokens;
            m_Request = request.SendWebRequest();
            m_Request.completed += UploadComplete;
          
            #if UNITY_ANALYTICS_EVENT_LOGS
            Debug.Log("Uploading events...");
            #endif
        }

void UploadComplete(AsyncOperation _)
        {
            long code = m_Request.webRequest.responseCode;

            #if UNITY_ANALYTICS_EVENT_LOGS
            Debug.Assert(code == 204, "Incorrect response, check your JSON for errors.");
            #endif

            if (!m_Request.webRequest.isNetworkError && code == 204)
            {
                #if UNITY_ANALYTICS_EVENT_LOGS
                Debug.LogFormat("Events uploaded successfully!", code);
                #endif

                // Remove the sent tokens from the buffer because they were accepted
                m_DataBuffer.RemoveSentTokens(m_RequestSentTokens);

                // We have got the internet so the disk cache is no longer needed.
                // If the internet fails again, we will flush the buffer from scratch at that time.
                m_DataBuffer.ClearDiskCache();
            }
            else
            {
                #if UNITY_ANALYTICS_EVENT_LOGS
                if (m_Request.webRequest.isNetworkError)
                {
                    Debug.Log("Events failed to upload (network error) -- will retry at next heartbeat.");
                }
                else
                {
                    Debug.LogFormat("Events failed to upload (code {0}) -- will retry at next heartbeat.", code);
                }
                #endif
                m_DataBuffer.FlushToDisk();
            }

            // Clear the request to allow another request to be sent.
            m_Request.webRequest.Dispose();
            m_Request = null;
        }

@LucianTheFak Do you have another JSON library in your project? Please share the code you are using to send the event.

I’m not sure, is there a way I can check if I have another one?
As for the code:

async void Start() {
        await UnityServices.InitializeAsync();
        if (!AuthenticationService.Instance.IsSignedIn) {
            await AuthenticationService.Instance.SignInAnonymouslyAsync();
        }
    }

    public void OnPlayerDeath() {
        string difficultyMethod = "";
        switch (DifficultyManager.instance.difficultyMethod) {
            case 1:
                difficultyMethod = "Predetermined";
                break;
            case 2:
                difficultyMethod = "Sandbox";
                break;
            case 3:
                difficultyMethod = "Dynamic";
                break;
        }
        Dictionary<string, object> parameters = new Dictionary<string, object>()
        {
            { "difficultyMethod", difficultyMethod }
        };
        Events.CustomData("playerDeath", parameters);
        Events.Flush();
    }

I’m trying to send this playerDeath event when my player dies.

Please show a screenshot of the assets and packages in the Project view, and a screenshot of your Package Manager, we can check for a duplicate library. Have you checked that difficultyMethod is not null? You don’t have a default case in your switch statement. Add the following just before your custom event call, the output will show in the Console window.

Debug.Log("difficultyMethod value = " + difficultyMethod.ToString());

difficultyMethod isn’t null, it gets set to one of the 3 cases at the start of the game. It printed out just fine.

Project View:
7755822--976305--upload_2021-12-22_16-26-57.png

7755822--976296--upload_2021-12-22_16-22-16.png

Package Manager:
7755822--976299--upload_2021-12-22_16-22-40.png

All the other packages in the project are mostly just models.

Yes, you’ve imported NewtsonSoft JSON. I might suggest testing your code in a new/empty project without it and compare. Are you actually using all these packages in your game? Generally you only import what you need.

To be honest, I’m not sure where that one came from. I can try it in a new project, but would it work if I just deleted NewtsonSoft from Packages?

You would want to make a full project backup before deleting components. Another package that you’ve imported may depend on it, but you can certainly try.

It seems the Version Control package was dependent on NewtsonSoft, but I’m not using Collaborate in this project. But I see that the Authentication package lists NewtsonSoft in its dependencies, so I don’t know if I can remove it.

7755939--976326--upload_2021-12-22_17-0-5.png

One way to find out! I have Authentication in my project too, but I don’t see the NewtonSoft package separately like in your screenshot. Please follow my previous suggestion with a new project to confirm. Don’t break your current project.

I just created a new project and some packages were automatically installed. NewtonSoft wasn’t there.
I install the Analytics and Authentication packages, and then the NewtonSoft folder appears in the Packages.
7756056--976344--upload_2021-12-22_17-24-10.png
It appears that the Authentication package puts it there, since it lists it under its dependencies.