Skip to content
This repository was archived by the owner on Aug 28, 2025. It is now read-only.

Repository files navigation

promoted-ruby-client

Ruby client designed for calling Promoted's Delivery and Metrics API.

More information at http://www.promoted.ai

Installation

gem 'promoted-ruby-client'

Local Development

  1. Clone or fork the repo on your local machine
  2. cd promoted-ruby-client
  3. bundle
  4. To test interactively: irb -Ilib -rpromoted/ruby/client

Dependencies

HTTP client for calling Promoted.

Faraday binding (provides connection pool support)

Provides a thread pool for making shadow traffic requests to Delivery API in the background on a subset of calls to deliver

Creating a Client

client=Promoted::Ruby::Client::PromotedClient.new

This client will suffice for building log requests. To send actually send traffing to the API, some configuration is required.

client=Promoted::Ruby::Client::PromotedClient.new({:metrics_endpoint=>"https://<get this from Promoted>",:delivery_endpoint=>"https://<get this from Promoted>",:metrics_api_key=>"<get this from Promoted>",:delivery_api_key=>"<get this from Promoted>"})

Client Configuration Parameters

NameTypeDescription
:delivery_endpointStringPOST URL for the Promoted Delivery API (get this from Promoted)
:metrics_endpointStringPOST URL for the Promoted Metrics API (get this from Promoted)
:metrics_api_keyStringUsed as the x-api-key header on Metrics API requests to Promoted (get this value from Promoted)
:delivery_api_keyStringUsed as the x-api-key header on Delivery API requests to Promoted (get this value from Promoted)
:delivery_timeout_millisNumberTimeout on the Delivery API call. Defaults to 3000.
:metrics_timeout_millisNumberTimeout on the Metrics API call. Defaults to 3000.
:perform_checksBooleanWhether or not to perform detailed input validation, defaults to true but may be disabled for performance
:loggerRuby Logger-compatible loggerDefaults to nil (no logging). Example: Logger.new(STDERR, :progname => 'promotedai')
:shadow_traffic_delivery_percentNumber between 0 and 1% of deliver traffic that gets directed to Delivery API as "shadow traffic". Defaults to 0 (no shadow traffic).
:send_shadow_traffic_for_controlBooleanIf true, the deliver method will send shadow traffic for users in the CONTROL arm of an experiment. Defaults to true.
:default_request_headersHashAdditional headers to send on the request beyond x-api-key. Defaults to {}
:default_only_logBooleanIf true, the deliver method will not direct traffic to Delivery API but rather return a request suitable for logging. Defaults to false.
:should_apply_treatment_funcProcCalled during delivery, accepts an experiment and returns a Boolean indicating whether the request should be considered part of the control group (false) or in the experiment (true). If nil, the default behavior of checking the experiement :arm is applied.
:warmupBooleanIf true, the client will prime the Net::HTTP::Persistent connection pool on construction; this can make the first few calls to Promoted complete faster. Defaults to false.
:max_request_insertionsNumberMaximum number of request insertions that will be passed to Delivery API on a single request (any more will be truncated by the SDK). Defaults to 1000.

Data Types

UserInfo

Basic information about the request user.

Field NameTypeOptional?Description
:user_idStringYesThe platform user id, cleared from Promoted logs.
:anon_user_idStringYesA different user id (presumably a UUID) disconnected from the platform user id, good for working with unauthenticated users or implementing right-to-be-forgotten.
:is_internal_userBooleanYesIf this user is a test user or not, defaults to false.
:ignore_usageBooleanYesIf you want to ignore usage from this user, defaults to false.

CohortMembership

Useful fields for experimentation during the delivery phase.

Field NameTypeOptional?Description
:user_infoUserInfoYesThe user info structure.
:armStringYes'CONTROL' or one of the TREATMENT values (see constants.rb).

Properties

Properties bag. Has the structure:

:struct=>{:product=>{"id": "product3","title": "Product 3","url": "www.mymarket.com/p/3"# other key-value pairs...}}

Insertion

Content being served at a certain position.

Field NameTypeOptional?Description
:user_infoUserInfoYesThe user info structure.
:insertion_idStringYesGenerated by the SDK (do not set)
:request_idStringYesGenerated by the SDK when needed (do not set)
:content_idStringNoIdentifier for the content to be shown, must be set.
:retrieval_rankNumberYesOptional original ranking of this content item.
:retrieval_scoreNumberYesOptional original quality score of this content item.
:propertiesPropertiesYesAny additional custom properties to associate. For v1 integrations, it is fine not to fill in all the properties.

Size

User's screen dimensions.

Field NameTypeOptional?Description
:widthIntegerNoScreen width
:heightIntegerNoScreen height

Screen

State of the screen including scaling.

Field NameTypeOptional?Description
:sizeSizeYesScreen size
:scaleFloatYesCurrent screen scaling factor

ClientHints

Alternative to user-agent strings. See https://raw.githubusercontent.com/snowplow/iglu-central/master/schemas/org.ietf/http_client_hints/jsonschema/1-0-0

Field NameTypeOptional?Description
:is_mobileBooleanYesMobile flag
:brandArray of ClientBrandHintYes
:architectureStringYes
:modelStringYes
:platformStringYes
:platform_versionStringYes
:ua_full_versionStringYes

ClientBrandHint

See https://raw.githubusercontent.com/snowplow/iglu-central/master/schemas/org.ietf/http_client_hints/jsonschema/1-0-0

Field NameTypeOptional?Description
:brandStringYesMobile flag
:versionStringYes

Location

Information about the user's location.

Field NameTypeOptional?Description
:latitudeFloatNoLocation latitude
:longitudeFloatNoLocation longitude
:accuracy_in_metersIntegerYesLocation accuracy if available

Browser

Information about the user's browser.

Field NameTypeOptional?Description
:user_agentStringYesBrowser user agent string
:viewport_sizeSizeYesSize of the browser viewport
:client_hintsClientHintsYesHTTP client hints structure
referrerStringYesRequest referrer

Device

Information about the user's device.

Field NameTypeOptional?Description
:device_typeone of (UNKNOWN_DEVICE_TYPE, DESKTOP, MOBILE, TABLET)YesType of device
:brandStringYes"Apple, "google", Samsung", etc.
:manufacturerStringYes"Apple", "HTC", Motorola", "HUAWEI", etc.
:identifierStringYesAndroid: android.os.Build.MODEL; iOS: iPhoneXX,YY, etc.
:screenScreenYesScreen dimensions
:ip_addressStringYesOriginating IP address
:locationLocationYesLocation information
:browserBrowserYesBrowser information

Paging

Paging parameters.

DeliveryRequest.retrieval_insertion_offset also impacts paging. That field indicate the offset of the retrieved insertions that are passed into Request.insertion. See detailed documentation on paging and retrieval_insertion_offset.

Field NameTypeOptional?Description
:offsetIntegerYesThe 0-based, starting index for the response page. This should be the global position.
:sizeIntegerYesThe number of items to return in a response page.

Request

A request for content insertions.

Field NameTypeOptional?Description
:user_infoUserInfoYesThe user info structure.
:request_idStringYesGenerated by the SDK when needed (do not set)
:use_caseStringYesOne of the use case values, i.e. 'FEED' (see constants.rb).
:propertiesPropertiesYesAny additional custom properties to associate.
:pagingPagingYesPaging parameters
:deviceDeviceYesDevice information (as available)
:disable_personalizationBooleanYesIf true, disables personalized inputs into Delivery algorithm.

DeliveryRequest

Input to deliver

Field NameTypeOptional?Description
:experimentCohortMembershipYesA cohort to evaluation in experimentation.
:requestRequestNoThe underlying request for content.
:only_logBooleanYesDefaults to false. Set to true to override whether Delivery API is called for this request.
:retrieval_insertion_offsetIntegerYesThe index of the retrieved insertions set on Request.insertion list. If just sending the top-N from your retrieval, this is 0. If this is the next batch (e.g. 500 to 999), then the value is 500. This can be used to send multiple groups of retrieved insertions. This interacts with the Paging fields. More detailed documentation on paging.

LogRequest

A log object that is sent as a RPC request to Promoted's Metrics API log endpoint. This is outputted from the deliver SDK call. Callers need to either input it into the send_log_request method or send it to the Metrics API directly. Clients should avoid manipulating this object directly.

ClientResponse

Output of deliver, includes the insertions as well as a suitable LogRequest for forwarding to Metrics API.

Field NameTypeOptional?Description
:insertion[] of InsertionNoThe paged insertions, which are from Delivery API (when deliver was called, i.e. we weren't either only-log or part of an experiment) or the input insertions (when the other conditions don't hold).
:log_requestLogRequestYesA message suitable for logging to Metrics API via send_log_request. If the call to deliver was made (i.e. the request was not part of the CONTROL arm of an experiment or marked to only log), :log_request will not be set, as you can assume logging was performed on the server-side by Promoted.
:client_request_idStringYesClient-generated request id sent to Delivery API and may be useful for logging and debugging.
:execution_serverone of 'API' or 'SDK'YesIndicates if response insertions on a delivery request came from the API or the SDK.

PromotedClient

MethodInputOutputDescription
send_log_requestLogRequestn/aForwards a LogRequest to Promoted using an HTTP client.
deliverDeliveryRequestClientResponseDepending on flags, either (1) makes a request (subject to experimentation) to Delivery API for insertions, which are then returned along with a LogRequest or (2) implements SDK-side paging and prepares log records that can be logged to Promoted using send_log_request or by using this structure to make the call yourself. Optionally, based on client configuration may send a random subset of requests to Delivery API as shadow traffic for integration purposes.
closen/an/aCloses down the client at shutdown, currently this is just to drain the thread pool that handles shadow traffic.

Metrics API

Expected flow for Metrics logging

# Retrieve a list of content (i.e. products)# products = fetch_my_marketplace_products()products=[{id: "123",type: "SHOE",name: "Blue shoe",total_sales: 1000},{id: "124",type: "SHIRT",name: "Green shirt",total_sales: 800},{id: "125",type: "DRESS",name: "Red dress",total_sales: 1200}]# Transform them into an [] of Insertions.insertions=products.map{ |product| {:content_id=>product[:id],:properties=>{:struct=>{:type=>product[:type],:name=>product[:name]# etc}}}}# Form a MetricsRequestmetrics_request={:request=>{:user_info=>{:user_id=>"912",:anon_user_id=>"912191"},:use_case=>"FEED",:paging=>{:offset=>0,:size=>5},:properties=>{:struct=>{:active=>true}},:insertion=>insertions},:only_log=>true,}# Create a clientclient=Promoted::Ruby::Client::PromotedClient.new# Build a log requestclient_response=client.deliver(metrics_request)# Log (assuming you have configured your client with a :metrics_endpoint)client.send_log_request(client_response[:log_request])ifclient_response[:log_request]

Delivery API

Expected flow for Delivery

# (continuing from the above example for Metrics)# Form a DeliveryRequestdelivery_request={:request=>{:user_info=>{:user_id=>"912",:anon_user_id=>"912191"},:use_case=>"FEED",:paging=>{:offset=>0,:size=>5},:properties=>{:struct=>{:active=>true}},:insertion=>insertions,},:only_log=>false}# Request insertions from Delivery APIclient_response=client.deliver(delivery_request)# Use the resulting insertionsclient_response[:insertion]# Log if a log request was provided (if not, deliver was called successfully# and Promoted logged on the server-side).)client.send_log_request(client_response[:log_request])ifclient_response[:log_request]

TODO Experimentation example

About

A Ruby client to contact Promoted APIs

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages