Open MarkEdmondson1234 opened 2 years ago
A plumber script:
library(measurementProtocol)
# get mp_secret from env MP_SECRET
#* Home page
#* @get /
#* @serializer html
function() {
"<html>
<h1>measurementProtocol + plumber</h1>
<p>POST to /gtm?ga_id=G-123456<p>
<p>Debug via /gtm?ga_id=G-123456&debug=1<p>
<p><a href=/__docs__/>Swagger docs</a>
</html>"
}
#* Send forward a measurement protocol hit
#* @post /gtm
#* @serializer unboxedJSON
#* @parser json
function(req, ga_id, debug = 0) {
pubsub_data <- jsonlite::fromJSON(req$postBody)
if(is.null(pubsub_data$message) ||
is.null(pubsub_data$message$data)){
res$status <- 400 # bad request
return(list(error="Pub/Sub Message Data was invalid"))
}
message <- pubsub_data$message
the_data <- rawToChar(jsonlite::base64_dec(message$data))
parsed <- suppressMessages(mp_parse_gtm(the_data))
my_connection <- mp_connection(ga_id)
message(
sprintf("Sending event: %s for client.id %s",
parsed$mp_event$name,
parsed$user$client_id)
)
sent <- mp_send(parsed$mp_event,
client_id = parsed$user$client_id,
user_id = parsed$user$user_id,
user_properties = parsed$user$user_properties,
connection = my_connection,
debug_call = if(debug != 0) TRUE else FALSE)
if(!isTRUE(sent)){
res$status <- 400 # bad request
return(list(error="MP hit failed to send"))
}
"OK"
}
A Dockerfile for Cloud Run
FROM gcr.io/gcer-public/measurementprotocol
COPY . ./api
ENTRYPOINT ["R", "-e", "pr <- plumber::plumb(rev(commandArgs())[1]); pr$run(host='0.0.0.0', port=as.numeric(Sys.getenv('PORT')), swagger=TRUE)"]
CMD ["/api/api.R"]
A googleCloudRunner deployment to Cloud Run
cr_deploy_plumber(
"inst/plumber",
remote = "measurement_protocol_proxy",
env_vars = paste0("MP_SECRET=", Sys.getenv("MP_SECRET"))
)
It is working
This is helpful if say you are passing your GA4 events to Pub/Sub in GTM-ServerSide.
GA4 tag on website sends hit -> GTM-SS takes event and publishes to Pub/Sub topic -> Pub/Sub subscription of the topic pushes to Cloud Run -> Cloud Run running plumber and this library receives JSON and parses it in MP hit.
A generic
mp_parse_json()
is now included to help facilitate parsing any JSON structure to MP, and anmp_parse_gtm()
function for the JSON structure coming from GTM.Example JSON from GTM-SS events:
Some example R code using the function for GTM as outlined above:
The above function uses the below functions: