Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
93c325a
allow screen_view and ad_impression events
lindsey-volta Aug 27, 2025
a79e34a
allow geo information fields
lindsey-volta Aug 27, 2025
ba03bc3
add support for geo fields
lindsey-volta Aug 28, 2025
d0a2dd2
update ip_override description
lindsey-volta Aug 28, 2025
cbfa48e
revert formatting changes
lindsey-volta Aug 28, 2025
efcaf90
Merge branch 'main' into event-builder-updates
lindsey-volta Aug 29, 2025
c293e02
revert ad_impression and screen_view changes
lindsey-volta Sep 4, 2025
21a48b8
reorder form fields
lindsey-volta Sep 5, 2025
35c6ffe
initial changes for device fields
lindsey-volta Sep 5, 2025
7d040eb
simplify implementation
lindsey-volta Sep 5, 2025
34ed75d
continue simplify implementation, cleanup files
lindsey-volta Sep 5, 2025
ada8047
add back labels for geo info
lindsey-volta Sep 5, 2025
8bf9f1b
additional file cleanup
lindsey-volta Sep 5, 2025
e10525e
Merge branch 'event-builder-updates' into new-device-fields
lindsey-volta Sep 5, 2025
91fe7b0
cleanup form descriptions and labels
lindsey-volta Sep 5, 2025
d051c96
add user_agent when client is gtag
lindsey-volta Sep 8, 2025
5969cf3
revert changes for useTextBox persistence fix, moreved to separate PR
lindsey-volta Sep 9, 2025
6660de6
Merge remote-tracking branch 'origin/main' into event-builder-updates
lindsey-volta Sep 10, 2025
e031057
Merge branch 'event-builder-updates' into new-device-fields
lindsey-volta Sep 10, 2025
7f86232
add user_agent field to payload
lindsey-volta Sep 10, 2025
b65393a
Merge remote-tracking branch 'origin/main' into event-builder-updates
lindsey-volta Sep 15, 2025
105971f
Merge branch 'event-builder-updates' into new-device-fields
lindsey-volta Sep 15, 2025
6a28bb2
add ip_override and user_location to test
lindsey-volta Sep 15, 2025
fc5fba4
Merge branch 'event-builder-updates' into new-device-fields
lindsey-volta Sep 15, 2025
6f48152
add device and user_agent fields to test
lindsey-volta Sep 15, 2025
b20dab6
Merge remote-tracking branch 'origin/main' into new-device-fields
lindsey-volta Sep 18, 2025
20ac90b
remove unnecessary else
lindsey-volta Sep 18, 2025
d635c88
fix merge conflict update
lindsey-volta Sep 18, 2025
207bbd8
resolve conflict issues
lindsey-volta Sep 18, 2025
263342a
update helper text
lindsey-volta Sep 19, 2025
29952ee
update device description
lindsey-volta Sep 19, 2025
61755d2
Merge branch 'main' into new-device-fields
lindsey-volta Sep 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 214 additions & 0 deletions src/components/ga4/EventBuilder/DeviceInformation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import React, { useContext } from "react"
import Chip from "@mui/material/Chip"
import Divider from "@mui/material/Divider"
import { styled } from "@mui/material/styles"
import Typography from "@mui/material/Typography"
import TextField from "@mui/material/TextField"
import Grid from "@mui/material/Grid"

import ExternalLink from "@/components/ExternalLink"
import { Label } from "./types"
import { UseFirebaseCtx } from "."

const Root = styled("div")(({ theme }) => ({
marginTop: theme.spacing(1),
}))

type DeviceInformationProps = {
device_category: string | undefined
setDeviceCategory: (value: string) => void
device_language: string | undefined
setDeviceLanguage: (value: string) => void
device_screen_resolution: string | undefined
setDeviceScreenResolution: (value: string) => void
device_operating_system: string | undefined
setDeviceOperatingSystem: (value: string) => void
device_operating_system_version: string | undefined
setDeviceOperatingSystemVersion: (value: string) => void
device_model: string | undefined
setDeviceModel: (value: string) => void
device_brand: string | undefined
setDeviceBrand: (value: string) => void
device_browser: string | undefined
setDeviceBrowser: (value: string) => void
device_browser_version: string | undefined
setDeviceBrowserVersion: (value: string) => void
user_agent: string | undefined
setUserAgent: (value: string) => void
}

const DeviceInformation: React.FC<DeviceInformationProps> = ({
device_category,
setDeviceCategory,
device_language,
setDeviceLanguage,
device_screen_resolution,
setDeviceScreenResolution,
device_operating_system,
setDeviceOperatingSystem,
device_operating_system_version,
setDeviceOperatingSystemVersion,
device_model,
setDeviceModel,
device_brand,
setDeviceBrand,
device_browser,
setDeviceBrowser,
device_browser_version,
setDeviceBrowserVersion,
user_agent,
setUserAgent,
}) => {
const useFirebase = useContext(UseFirebaseCtx)
const docHref =
"https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference#device"
return (
<Root>
<Divider>
<Chip label="DEVICE INFORMATION" size="small" />
</Divider>
<Typography variant="h6">Device Attributes</Typography>
<Typography>
See the{" "}
<ExternalLink href={docHref}>documentation</ExternalLink> for more
information about device attributes.
</Typography>
<Grid container spacing={1}>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-category"
label={Label.DeviceCategory}
variant="outlined"
size="small"
value={device_category || ""}
onChange={e => setDeviceCategory(e.target.value)}
helperText="The category of the device, e.g., mobile, desktop"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-language"
label={Label.DeviceLanguage}
variant="outlined"
size="small"
value={device_language || ""}
onChange={e => setDeviceLanguage(e.target.value)}
helperText="The language of the device in ISO 639-1 format, e.g., en"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-screen-resolution"
label={Label.DeviceScreenResolution}
variant="outlined"
size="small"
value={device_screen_resolution || ""}
onChange={e => setDeviceScreenResolution(e.target.value)}
helperText="The screen resolution of the device, e.g., 1920x1080"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-operating-system"
label={Label.DeviceOperatingSystem}
variant="outlined"
size="small"
value={device_operating_system || ""}
onChange={e => setDeviceOperatingSystem(e.target.value)}
helperText="The device's operating system, e.g., MacOS, Windows"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-operating-system-version"
label={Label.DeviceOperatingSystemVersion}
variant="outlined"
size="small"
value={device_operating_system_version || ""}
onChange={e => setDeviceOperatingSystemVersion(e.target.value)}
helperText="The version of the device's operating system, e.g., 13.5"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-model"
label={Label.DeviceModel}
variant="outlined"
size="small"
value={device_model || ""}
onChange={e => setDeviceModel(e.target.value)}
helperText="The model of the device, e.g., Pixel 6"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-brand"
label={Label.DeviceBrand}
variant="outlined"
size="small"
value={device_brand || ""}
onChange={e => setDeviceBrand(e.target.value)}
helperText="The brand of the device, e.g., Google"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-browser"
label={Label.DeviceBrowser}
variant="outlined"
size="small"
value={device_browser || ""}
onChange={e => setDeviceBrowser(e.target.value)}
helperText="The brand or type of browser, e.g., Chrome"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="device-browser-version"
label={Label.DeviceBrowserVersion}
variant="outlined"
size="small"
value={device_browser_version || ""}
onChange={e => setDeviceBrowserVersion(e.target.value)}
helperText="The browser version, e.g., 136.0.7103.60"
/>
</Grid>
</Grid>
{!useFirebase && (
<>
<Typography variant="h6">User Agent</Typography>
<Typography>
Provide a custom user agent string. Google Analytics will use this to derive information
about the user's device, operating system, and browser. This field is ignored if device
attributes are provided.
</Typography>
<Grid container spacing={1}>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
id="user-agent"
label={Label.UserAgent}
variant="outlined"
size="small"
value={user_agent || ""}
onChange={e => setUserAgent(e.target.value)}
helperText="The user agent string identifying the client"
/>
</Grid>
</Grid>
</>
)}
</Root>
)
}

export default DeviceInformation
14 changes: 13 additions & 1 deletion src/components/ga4/EventBuilder/ValidateEvent/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,19 @@ const renderComponent = (props: Partial<ValidateEventProps> = {}) => {
country_id: "US",
subcontinent_id: "021",
continent_id: "019"
}
},
user_agent: "",
device: {
category: "mobile",
language: "en",
screen_resolution: "1280x2856",
operating_system: "Android",
operating_system_version: "14",
model: "Pixel 9 Pro",
brand: "Google",
browser: "Chrome",
browser_version: "136.0.7103.60"
}
}

return render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { userPropertiesSchema } from './userProperties'
import { eventsSchema } from './events'
import { userLocationSchema } from "./userLocation"
import { deviceSchema } from "./deviceSchema"

export const baseContentSchema = {
type: "object",
Expand Down Expand Up @@ -31,5 +32,9 @@ export const baseContentSchema = {
ip_override: {
type: "string",
},
device: deviceSchema,
user_agent: {
type: "string",
}
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export const deviceSchema = {
type: "object",
additionalProperties: false,
properties: {
category: {
type: "string",
},
language: {
type: "string",
},
screen_resolution: {
type: "string",
},
operating_system: {
type: "string",
},
operating_system_version: {
type: "string",
},
model: {
type: "string",
},
brand: {
type: "string",
},
browser: {
type: "string",
},
browser_version: {
type: "string",
},
},
};
17 changes: 16 additions & 1 deletion src/components/ga4/EventBuilder/ValidateEvent/usePayload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ const usePayload = (): {} => {
payloadObj,
ip_override,
user_location,
device,
user_agent
} = useContext(EventCtx)!

const eventName = useMemo(() => {
Expand Down Expand Up @@ -116,13 +118,24 @@ const usePayload = (): {} => {
return cleaned_location
}, [user_location])

const device_info = useMemo(() => {
if (device === undefined) {
return undefined
}
const cleaned_device = removeUndefined(device)
if (Object.keys(cleaned_device).length === 0) {
return undefined
}
return cleaned_device
}, [device])

let payload = useMemo(() => {
return {
...removeUndefined(clientIds),
...removeUndefined({ timestamp_micros }),
...removeUndefined({ non_personalized_ads }),
...removeUndefined(removeEmptyObject({ user_properties })),
...removeUndefined({ ip_override, user_location: user_location_info }),
...removeUndefined({ ip_override, user_location: user_location_info, device: device_info, user_agent }),
events: [
{ name: eventName, ...(parameters.length > 0 ? { params } : {}) },
],
Expand All @@ -137,6 +150,8 @@ const usePayload = (): {} => {
user_properties,
ip_override,
user_location_info,
device_info,
user_agent
])

if (useTextBox) {
Expand Down
Loading
Loading