diff --git a/reflex_ui/blocks/telemetry/__init__.py b/reflex_ui/blocks/telemetry/__init__.py new file mode 100644 index 0000000..60b8395 --- /dev/null +++ b/reflex_ui/blocks/telemetry/__init__.py @@ -0,0 +1,18 @@ +"""Telemetry blocks for the Reflex UI library.""" + +from .clearbit import get_clearbit_trackers +from .common_room import get_common_room_trackers, identify_common_room_user +from .google import get_google_analytics_trackers +from .koala import get_koala_trackers +from .posthog import get_posthog_trackers +from .rb2b import get_rb2b_trackers + +__all__ = [ + "get_clearbit_trackers", + "get_common_room_trackers", + "get_google_analytics_trackers", + "get_koala_trackers", + "get_posthog_trackers", + "get_rb2b_trackers", + "identify_common_room_user", +] diff --git a/reflex_ui/blocks/telemetry/clearbit.py b/reflex_ui/blocks/telemetry/clearbit.py new file mode 100644 index 0000000..5e235b2 --- /dev/null +++ b/reflex_ui/blocks/telemetry/clearbit.py @@ -0,0 +1,22 @@ +"""Clearbit analytics tracking integration for Reflex applications.""" + +import reflex as rx + +CLEARBIT_SCRIPT_URL_TEMPLATE: str = ( + "https://tag.clearbitscripts.com/v1/{public_key}/tags.js" +) + + +def get_clearbit_trackers(public_key: str) -> rx.Component: + """Generate Clearbit tracking component for a Reflex application. + + Args: + public_key: Clearbit public key (defaults to app's public key) + + Returns: + rx.Component: Script component needed for Clearbit tracking + """ + return rx.el.script( + src=CLEARBIT_SCRIPT_URL_TEMPLATE.format(public_key=public_key), + referrer_policy="strict-origin-when-cross-origin", + ) diff --git a/reflex_ui/blocks/telemetry/common_room.py b/reflex_ui/blocks/telemetry/common_room.py new file mode 100644 index 0000000..5a89be5 --- /dev/null +++ b/reflex_ui/blocks/telemetry/common_room.py @@ -0,0 +1,77 @@ +"""Common Room website visitor tracking integration for Reflex applications.""" + +import json + +import reflex as rx + +# Common Room tracking configuration +COMMON_ROOM_CDN_URL_TEMPLATE: str = ( + "https://cdn.cr-relay.com/v1/site/{site_id}/signals.js" +) + +# Common Room tracking script template +COMMON_ROOM_SCRIPT_TEMPLATE: str = """ +(function() {{ + if (typeof window === 'undefined') return; + if (typeof window.signals !== 'undefined') return; + var script = document.createElement('script'); + script.src = '{cdn_url}'; + script.async = true; + window.signals = Object.assign( + [], + ['page', 'identify', 'form', 'track'].reduce(function (acc, method) {{ + acc[method] = function () {{ + signals.push([method, arguments]); + return signals; + }}; + return acc; + }}, {{}}) + ); + document.head.appendChild(script); +}})(); +""" + + +def get_common_room_trackers(site_id: str) -> rx.Component: + """Generate Common Room tracking component for a Reflex application. + + Args: + site_id: Your Common Room site ID (found in your tracking snippet) + + Returns: + rx.Component: Script component needed for Common Room tracking + """ + cdn_url = COMMON_ROOM_CDN_URL_TEMPLATE.format(site_id=site_id) + + return rx.script(COMMON_ROOM_SCRIPT_TEMPLATE.format(cdn_url=cdn_url)) + + +def identify_common_room_user( + email: str, name: str | None = None +) -> rx.event.EventSpec: + """Identify a user in Common Room analytics after form submission or login. + + This should be called when you have user identity information available, + such as after a form submission or user login. + + Args: + email: User's email address + name: User's full name (optional) + + Returns: + rx.Component: Script component that identifies the user in Common Room + """ + identify_data = {"email": email} + if name: + identify_data["name"] = name + + js_data = json.dumps(identify_data) + + return rx.call_script( + f""" + // Identify user in Common Room after form submission or login + if (typeof window.signals !== 'undefined' && window.signals.identify) {{ + window.signals.identify({js_data}); + }} + """ + ) diff --git a/reflex_ui/blocks/telemetry/google.py b/reflex_ui/blocks/telemetry/google.py new file mode 100644 index 0000000..3a4ca2d --- /dev/null +++ b/reflex_ui/blocks/telemetry/google.py @@ -0,0 +1,36 @@ +"""Google Analytics tracking integration for Reflex applications.""" + +import reflex as rx + +# Google Tag Manager script template +GTAG_SCRIPT_TEMPLATE: str = """ +window.dataLayer = window.dataLayer || []; +function gtag() {{ + window.dataLayer.push(arguments); +}} +gtag('js', new Date()); +gtag('config', '{tracking_id}'); +""" + +# Google Tag Manager script URL template +GTAG_SCRIPT_URL_TEMPLATE: str = ( + "https://www.googletagmanager.com/gtag/js?id={tracking_id}" +) + + +def get_google_analytics_trackers( + tracking_id: str, +) -> list[rx.Component]: + """Generate Google Analytics tracking components for a Reflex application. + + Args: + tracking_id: Google Analytics tracking ID (defaults to app's tracking ID) + + Returns: + list[rx.Component]: Script components needed for Google Analytics tracking + """ + # Load Google Tag Manager script + return [ + rx.script(src=GTAG_SCRIPT_URL_TEMPLATE.format(tracking_id=tracking_id)), + rx.script(GTAG_SCRIPT_TEMPLATE.format(tracking_id=tracking_id)), + ] diff --git a/reflex_ui/blocks/telemetry/koala.py b/reflex_ui/blocks/telemetry/koala.py new file mode 100644 index 0000000..6d687f1 --- /dev/null +++ b/reflex_ui/blocks/telemetry/koala.py @@ -0,0 +1,46 @@ +"""Koala analytics tracking integration for Reflex applications.""" + +import reflex as rx + +# Koala tracking configuration +KOALA_SCRIPT_URL_TEMPLATE: str = "https://cdn.getkoala.com/v1/{public_api_key}/sdk.js" + +# Koala initialization script template +KOALA_SCRIPT_TEMPLATE: str = """ +!function(t) {{ + if (window.ko) return; + window.ko = []; + [ + "identify", + "track", + "removeListeners", + "on", + "off", + "qualify", + "ready" + ].forEach(function(t) {{ + ko[t] = function() {{ + var n = [].slice.call(arguments); + return n.unshift(t), ko.push(n), ko; + }}; + }}); + var n = document.createElement("script"); + n.async = !0; + n.setAttribute("src", "{script_url}"); + (document.body || document.head).appendChild(n); +}}(); +""" + + +def get_koala_trackers(public_api_key: str) -> rx.Component: + """Generate Koala tracking component for a Reflex application. + + Args: + public_api_key: Koala public API key + + Returns: + rx.Component: Script component needed for Koala tracking + """ + script_url = KOALA_SCRIPT_URL_TEMPLATE.format(public_api_key=public_api_key) + + return rx.script(KOALA_SCRIPT_TEMPLATE.format(script_url=script_url)) diff --git a/reflex_ui/blocks/telemetry/posthog.py b/reflex_ui/blocks/telemetry/posthog.py new file mode 100644 index 0000000..8002488 --- /dev/null +++ b/reflex_ui/blocks/telemetry/posthog.py @@ -0,0 +1,81 @@ +"""PostHog analytics tracking integration for Reflex applications.""" + +import json + +import reflex as rx + +# PostHog tracking configuration +POSTHOG_API_HOST: str = "https://us.i.posthog.com" + +# PostHog initialization script template +POSTHOG_SCRIPT_TEMPLATE: str = """ +!function(t,e){{ + var o,n,p,r; + e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){{ + function g(t,e){{ + var o=e.split("."); + 2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){{ + t.push([e].concat(Array.prototype.slice.call(arguments,0))) + }} + }} + (p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","-assets.i.posthog.com")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r); + var u=e; + for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){{ + var e="posthog"; + return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e + }},u.people.toString=function(){{ + return u.toString(1)+".people (stub)" + }},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys getNextSurveyStep onSessionId setPersonProperties".split(" "),n=0;n rx.event.EventSpec: + """Identify a user in PostHog analytics. + + Args: + user_id: Unique identifier for the user + + Returns: + rx.event.EventSpec: Event specification for identifying the user in PostHog + """ + user_id = json.dumps(user_id) + + return rx.call_script( + f""" + if (typeof posthog !== 'undefined') {{ + posthog.identify({user_id}); + }} + """ + ) + + +def get_posthog_trackers( + project_id: str, + api_host: str = POSTHOG_API_HOST, +) -> rx.Component: + """Generate PostHog tracking component for a Reflex application. + + Args: + project_id: PostHog project ID (defaults to app's project ID) + api_host: PostHog API host URL (defaults to US instance) + + Returns: + rx.Component: Script component needed for PostHog tracking + """ + return rx.script( + POSTHOG_SCRIPT_TEMPLATE.format( + project_id=project_id, + api_host=api_host, + ) + ) diff --git a/reflex_ui/blocks/telemetry/rb2b.py b/reflex_ui/blocks/telemetry/rb2b.py new file mode 100644 index 0000000..677147b --- /dev/null +++ b/reflex_ui/blocks/telemetry/rb2b.py @@ -0,0 +1,47 @@ +"""RB2B (Reveal Bot to Bot) analytics tracking integration for Reflex applications.""" + +import reflex as rx + +# RB2B tracking script template +RB2B_SCRIPT_TEMPLATE: str = """ +!function () {{ + var reb2b = window.reb2b = window.reb2b || []; + if (reb2b.invoked) return; + reb2b.invoked = true; + reb2b.methods = ["identify", "collect"]; + reb2b.factory = function (method) {{ + return function () {{ + var args = Array.prototype.slice.call(arguments); + args.unshift(method); + reb2b.push(args); + return reb2b; + }}; + }}; + for (var i = 0; i < reb2b.methods.length; i++) {{ + var key = reb2b.methods[i]; + reb2b[key] = reb2b.factory(key); + }} + reb2b.load = function (key) {{ + var script = document.createElement("script"); + script.type = "text/javascript"; + script.async = true; + script.src = "https://s3-us-west-2.amazonaws.com/b2bjsstore/b/" + key + "/reb2b.js.gz"; + var first = document.getElementsByTagName("script")[0]; + first.parentNode.insertBefore(script, first); + }}; + reb2b.SNIPPET_VERSION = "1.0.1"; + reb2b.load("{api_key}"); +}}(); +""" + + +def get_rb2b_trackers(api_key: str) -> rx.Component: + """Generate RB2B tracking component for a Reflex application. + + Args: + api_key: Your RB2B API key (found in your RB2B dashboard) + + Returns: + rx.Component: Script component needed for RB2B tracking + """ + return rx.script(RB2B_SCRIPT_TEMPLATE.format(api_key=api_key))