Connect Google Analytics 4

Paste a Measurement ID and API secret, prove the connection with one event in GA4 Realtime, choose which events to send, and read the delivery log.

Connect Google Analytics 4

The Google Analytics 4 page has five numbered sections, and you work them top to bottom: connect a stream, decide what identity and privacy options apply, choose which events go to GA4, do the two things only you can do on Google's side, and then watch the delivery log. This article walks each section with its exact labels.

What You'll Need

Where the page is

Settings (the gear icon, top right) → Integrations → Google Analytics 4 (sign-in required: /settings/google-analytics)

A short callout at the top, Before you start, on Google's side, reminds you that the GA4 property must be linked to Google Ads with Enable Personalized Advertising on, and that auto-tagging must be on in Ads. Those are one-time settings in Google; the article returns to them in section 4.

Approval by Karmaflow.ai comes first

Before any of your data is sent to Google, a Karmaflow.ai platform admin approves your workspace. One approval covers sending events to GA4, uploading offline conversions and enhanced conversions for leads to Google Ads, and the audience features as they ship. It is Karmaflow.ai's own eligibility check; you remain responsible for Google's advertising, personalised advertising and data policies, and you confirm that when you ask.

The request sits at the top of the Google Analytics 4 page, above section 1, until you are approved:

  1. Choose Your business from the list.
  2. Enter your Business website.
  3. Say in a sentence or two How you will use Google Ads and Analytics with Karmaflow.
  4. Tick the box that confirms your responsibility for Google's policies.
  5. Press Request approval. The card changes to Waiting for Karmaflow approval, with who asked and when, and a Karmaflow.ai admin is emailed.

While you wait, the test event in section 1 still works, so you can prove the connection. Every other event is recorded under Recent deliveries as Not sent — awaiting Karmaflow approval. If the request is declined or approval is later withdrawn, the card shows the reason and lets you ask again. Once approved, the card shrinks to one green line. A workspace that was already sending events to GA4 before approval was required is approved automatically, and the line says so.

Section 1 — Connect a GA4 web data stream

Section 1 of the Google Analytics 4 settings page: Measurement ID and API secret fields, the data region, the status chip reading Confirmed in GA4, and the Send test event and I saw it in Realtime buttons

  1. Enter the Measurement ID. The field validates the shape as you type; a wrong shape shows Must look like G-XXXXXXXXXX under it and Save stays disabled.
  2. Paste the API secret. It is write-only: once saved, the field shows a saved marker and stays blank. Leaving it blank on a later save keeps the stored secret.
  3. Choose the Data region: Global (www.google-analytics.com) or EU (region1.google-analytics.com). This is the endpoint Karmaflow.ai's servers send to. Pick EU if your data-processing terms require requests to terminate in the EU; it does not change what GA4 stores.
  4. Press Save, then Send test event.

What the test proves, and what it cannot. Google checks the shape of the request on its validation endpoint but does not check the Measurement ID or the API secret: a wrong secret is accepted silently. So the test does two things. It validates the request shape, and it sends one live event named karmaflow_connection_test into your property. The status chip then reads Request accepted · confirm in GA4.

  1. In GA4 open Reports → Realtime, wait for karmaflow_connection_test to appear (usually under a minute), and press I saw it in Realtime on the Karmaflow.ai page. The chip becomes Confirmed in GA4 · G-….

The chip states, in order: Not configured → Not tested yet → Request accepted · confirm in GA4 → Confirmed in GA4. Sends can be turned on from the Request accepted state onward; the confirmation is your proof, not a gate.

Disconnect forgets the API secret and turns sends off. It is not the way to pause; that is the master switch in section 2.

Section 2 — Sending, identity and privacy

Each box saves as soon as you tick it.

Toggle Default What it does
Send events to GA4 off until a test has been accepted The master switch. Off keeps everything configured but sends nothing; the way to pause while you investigate a property.
Dry run (validation endpoint only) off Every event goes to Google's validation endpoint and lands nowhere. Rows in section 5 are marked (dry run). You will not see these events in Realtime or DebugView. Useful for a day, then turn it off.
Send the contact id as GA4 User-ID on Lets GA4 join one person across browsers when the property's reporting identity is Blended or Observed. The value is Karmaflow.ai's own id, never an email or phone.
Also send events for contacts with no captured web identity off Uses a stable synthetic client id per contact. GA4 counts each such contact as a new user with no traffic source, which inflates user counts and dilutes rates. Off means those events are listed as Not sent, no web identity.
Attach hashed email and phone (user-provided data) off SHA-256 hashes only, never for a contact marked Do Not Contact. Requires User-provided data collection to be on in the property (GA4 Admin → Data collection and modification → Data collection).
Send Consent Mode v2 signals with every event on Every event carries ad_user_data and ad_personalization: DENIED for a contact marked Do Not Contact, GRANTED for everyone else. Karmaflow.ai records opt-outs, not opt-ins. If you need recorded positive consent, keep your consent platform as the source and turn this off; then no consent block is sent.

Below the toggles, Default currency for values without one (three-letter code, its own Save) is used when an event carries a value but no currency.

Section 3 — Which events go to GA4

Section 3: the event map, one row per Karmaflow.ai trigger with an on/off box, the GA4 event name, and an expanded Conversation analyzed row showing its parameters and the outcome list that also sends generate_lead

Each row is one Karmaflow.ai trigger, with a checkbox, the GA4 event name (editable, letters, digits and underscores, starting with a letter, at most 40 characters, not a name Google reserves) and an expander listing the parameters that ride along. Before a stream is connected the map is read-only and shows what you would get out of the box.

Defaults, chosen so Smart Bidding learns from value rather than volume:

Trigger GA4 event On by default
Web form submitted generate_lead yes
Meeting booked meeting_booked yes
Deal stage changed deal_stage_changed, plus purchase with value and currency when the deal closes won yes
Call completed phone_call (direction, duration, who answered) yes
Conversation analyzed (outcome known) conversation_outcome (channel, outcome type, sentiment, agent id), plus generate_lead when the outcome type is in your list yes for new connections; New and off for workspaces connected earlier
Chat session started chat_started no
SMS received sms_inbound no
Ticket created / solved, CSAT, lifecycle changes, deal created as named no

The Conversation analyzed row has one extra control: also sends generate_lead when meta.outcomeType is one of followed by a comma list, default booked, appointment_booked, qualified, purchase. Type your own analytics prompt's outcome types, lowercase, and click away or press Enter to save. Only the outcome type is ever sent; the written outcome detail never leaves Karmaflow.ai.

Give an outcome a value

Smart Bidding bids to value only when the key event carries one. Out of the box only purchase does (the deal's own amount). For everything else, open a row's params and use value by rule: when a field = some text → value. Each rule is one line: pick the field (for the Conversation analyzed row, outcome_type), type the text to match (booked), and enter what that outcome is worth to you in your default currency (250). + a rule for each listed outcome pre-fills one line per outcome type in the row's generate_lead list, so you only type the numbers. Matching ignores case; an outcome with no rule sends no value; when the event already carries a number (a deal amount) that number wins. The value goes on the row's event and on the generate_lead it triggers, so whichever of the two you mark as a key event bids to it. Press Save event map.

Rows marked New were added to your map after you connected. They arrive off; tick the box when you want them.

Reset to defaults restores the shipped map. Every row also sends session_id and engagement_time_msec, which GA4 needs to place the event in a session.

Section 4 — On Google's side (we cannot do these for you)

  1. Link the GA4 property to Google Ads and turn on Enable Personalized Advertising on the link (GA4 Admin → Product links → Google Ads links). Keep auto-tagging on in Google Ads.
  2. Mark the events you want to bid on as key events in GA4 (Admin → Events), then in Google Ads Goals → Conversions → New → Import → Google Analytics. Imported key events appear in Ads within about a day. Mark only events you want Smart Bidding to chase.
  3. Audiences are built in GA4 from these events and export to the linked Ads account automatically once personalised advertising is on. Under the list, Audience recipes gives six ready-made ones with the event names from your map and a Copy steps button. See Build GA4 audiences from your conversations.

Two facts to set expectations: attribution works at the user level (an off-site event is credited to the ad click within your lookback window, default 90 days, but appears as a new session, never inside the original web session), and events need a captured web identity (see the overview).

Section 5 — Recent deliveries

Section 5: the deliveries table with a Sent row, a Not sent — no web identity row with its reason sentence, and a Rejected by Google row carrying Google's validation message

Every send attempt and every deliberate skip is a row: when, the trigger, the GA4 event name(s), the identity used (contact, chat_session, event_meta, synthetic, or none, plus + user_id), the result, and a Detail sentence. The table refreshes every 15 seconds while the page is open and shows the last time it read. Rows expire after 30 days.

Above the table, Last 7 days sums the log: how many contact events there were, how many were sent, how many were not sent, no web identity and what share that is, and how many failed. That share is your tracker health. When at least ten events were logged and half or more had no web identity, the line says so and names the two fixes: put the Karmaflow.ai tracker or chat widget on the pages visitors land on, or, if these contacts do not come through your site at all, turn on the synthetic option in section 2. Test sends are not counted.

Result Meaning
Sent Google accepted the request (or, in dry run, validated it).
Not sent — awaiting Karmaflow approval Your workspace is not approved yet; see the top of this article.
Not sent, no web identity The contact has no GA client id yet. The Detail sentence names the one setting that changes it.
Not sent, do not contact The contact is marked Do Not Contact and the row needed hashed user data.
Rejected by Google The validation endpoint returned messages; Detail shows them.
Could not reach Google The request failed after retries.

Keep test records out of your reports

Test deals and contacts reach GA4 like any other record — a test deal moved to closed won sends a real purchase. Instead of disconnecting while you test, mark your test records and filter them out in GA4:

  1. Tag the test contact or deal with a tag that starts with kftest — for example kftest, or kftest-demo — or give the test contact an email that starts with kftest (for example kftest+1@yourcompany.com).
  2. Every event about that record is still sent, with one extra parameter: kf_test_marker = kftest_record. The tag and the email themselves are never sent.
  3. In GA4, register kf_test_marker as an event-scoped custom dimension (Admin → Custom definitions → Create custom dimension).
  4. In any report, exploration or comparison, add the filter kf_test_marker does not match regex ^kftest. Real events have no marker, so they always pass.

In Recent deliveries, a row sent with the marker carries a line under its Detail saying it is test data, so you can tell why it is missing from a filtered report. Only a tag or email that starts with kftest counts: a tag like latest or a domain like kftest.example is real data.

Troubleshooting

The test says "Request accepted" but nothing appears in Realtime. The Measurement ID or the API secret belongs to a different stream, or the secret was revoked. Google does not report either; re-create the secret in GA4 for the stream whose id you pasted, save both again, and re-test.

A row says "Not sent, no web identity" for someone who did visit the site. The visit happened before the Karmaflow.ai tracker or widget was on the page, or the visitor never identified themselves there (no chat, no form, no tracked link). The identity is captured at that moment, not from the visit alone. See the workflows article.

The event map has no "Conversation analyzed" row. Reload the page; rows added since you connected are appended (off, marked New) when the page loads.

"Send events to GA4" is greyed out. A test event has not been accepted yet on this connection. Run Send test event in section 1.

Next steps