Introduction
Managed Data Sharing gives direct access to Billy Grace data inside your own data warehouse. The connection is set up once. The data keeps updating, with no limits on volume. We deliver it through Open Sharing, an open protocol built on Databricks. It works with or without a Databricks environment. Once connected, you can combine the shared tables with your own data. Use them for analysis, dashboards, workflows or models.
This is currently a beta feature. It doesn't carry a cost while we monitor usage during the testing phase. Our cost structure is heavily related to how much data you pull. Please use filters effectively.
To get started with Managed Data Sharing please get in touch with your Customer Success Manager or send an email to support@billygrace.com.
Who this is for
Managed Data Sharing puts table level data directly into your own environment. It's built for teams with data engineering or data analytics capacity. Setting this up takes ongoing ownership. That includes handling credentials and managing the data. If that capacity isn't in place yet, ask your Billy Grace contact if this is the right fit for now.
How it works
Open Sharing supports two connection modes. Which one applies depends on whether your organisation uses Databricks or another data warehouse.
Native Databricks access: for a Unity Catalog enabled Databricks workspace. We connect your metastore directly. The shared tables become discoverable inside your own workspace. No credential file to manage.
Token-based access: for everyone else. We create a recipient for your organisation and issue an access token. Connect from any tool that supports Open Sharing, including plain Python or Spark.
Either way, access is scoped per recipient. You only ever see the client data your organisation has been granted. That filtering happens server-side. It can't be bypassed from your end.
How data is delivered
Data is shared using a pull model. Whenever you query one of the tables below, the data is pulled from our data warehouse. The tables currently refresh daily and include all historical data available for you in the Billy Grace platform. You choose what to pull by selecting only the rows and columns you need, and every query returns the latest state.
Getting Started
Please reach out to your Billy Grace contact to determine whether Managed Data Sharing is a good fit for you. They'll guide you through the steps below and ask for the information needed for setup. Any confidential information is shared through a secure link.
Access
Native Databricks
Send your Unity Catalog metastore ID to your Billy Grace contact.
We open the share on our side.
The tables become discoverable in your workspace. No credential file. No token to manage. You can query them like any other table in your Databricks environment.
Token-based
Get in touch with your Billy Grace contact to set up token-based access, and choose the option that fits your organisation:
Option | How it works | Best for |
OIDC federation | You share your OIDC provider details with us. We link them to a recipient, and from that point on you generate your own short-lived tokens whenever you need access. | Organisations that already run an OIDC provider internally. |
Long-lived token | We create a recipient and generate a download link containing a token, valid for a duration you choose. When it expires, we issue a new one together. | A faster way to get started, no OIDC provider required. |
Contact your Billy Grace contact to request access, and confirm whether you want OIDC federation or a long-lived token.
We'll send you a one-time secure link. Following it downloads a credential file (config.share), which contains the sharing endpoint and your token. Treat it as a secret.
Install the delta-sharing Python package (pip install delta-sharing==1.4.2) and point it at your credential file to start reading tables, in plain Python/pandas, or with Spark for larger volumes. See Sample queries below.
Agencies
The brand always remains the owner of its data. If an agency wants to use Managed Data Sharing, the brand needs to confirm they're comfortable with that first.
What Data Is Shared
Daily performance data (daily_performance_data)
Daily aggregated performance per client, combining media spend, engagement and attributed conversions across all integrated channels. Each row represents one combination of date, event type, attribution model and window, and campaign dimensions.
Field Name | Data Type | Description | Required |
data_share_id | bigint | Unique identifier used for your organisation in the share | Yes |
client_id | int | Unique identifier for a client in Billy Grace | Yes |
ev | string | Event identifier, for example purchase or lead | Yes |
is_event_date | int | Flag indicating whether the date is the event date (1) or the session date (0) | Yes |
is_integrated_channel | int | Whether the row relates to a channel with a marketing integration connected (1) or not (0) | Yes |
attribution_model | string | Attribution model, one of mta (multi-touch attribution), umm (unified marketing measurement) or lc (last-click) | Yes |
attribution_window | string | Attribution window, one of unlimited (no window), 1_days, 7_days or 30_days | Yes |
date | date | Date of the record | Yes |
source | string | UTM source where tracking is placed, for example facebook, tiktok, google or email | Yes |
medium | string | UTM medium indicating the traffic medium, for example cpc, organic, referral or email | Yes |
campaign_id | bigint | Unique identifier for the campaign | No |
campaign_name | string | Name of the advertising campaign | No |
adset_id | bigint | Unique identifier of the ad set | No |
adset_name | string | Name of the ad set | No |
ad_id | bigint | Unique identifier of the ad | No |
ad_name | string | Name of the ad | No |
campaign_status | string | Current status of the campaign, for example ACTIVE or PAUSED | No |
adset_status | string | Current status of the ad set, for example ACTIVE or PAUSED | No |
ad_status | string | Current status of the ad, for example ACTIVE or PAUSED | No |
spend | float | Total advertising spend for the marketing channel | No |
clicks | int | Total number of clicks from the marketing channel | No |
impressions | int | Total number of ad impressions from the marketing channel | No |
video_p25_watched | int | Number of times the video was watched to 25% | No |
video_p50_watched | int | Number of times the video was watched to 50% | No |
video_p75_watched | int | Number of times the video was watched to 75% | No |
completed_video_views | int | Number of times the video was watched to completion | No |
pageviews | int | Total number of page views | No |
sessions | int | Total number of sessions | No |
number_of_events | float | Total number of conversion events | No |
event_value | float | Total monetary value of conversion events | No |
returning_customers | float | Number of returning customers | No |
new_customers | float | Number of new customers | No |
returning_customer_revenue | float | Revenue from returning customers | No |
new_customer_revenue | float | Revenue from new customers | No |
gross_profit | float | Gross profit (ad spend is not subtracted) | No |
Conversion data (conversion_data)
Integrated conversion data per client with device, geography and custom dimension breakdowns. Each row represents one combination of date, event type, attribution model and window, and campaign dimensions.
Field Name | Data Type | Description | Required |
data_share_id | bigint | Unique identifier used for your organisation in the share | Yes |
client_id | int | Unique identifier for a client in Billy Grace | Yes |
ev | string | Event identifier, for example purchase or lead | Yes |
is_event_date | int | Flag indicating whether the date is the event date (1) or the session date (0) | Yes |
is_integrated_channel | int | Whether the row relates to a channel with a marketing integration connected (1) or not (0) | No |
attribution_model | string | Attribution model, one of mta (multi-touch attribution), umm (unified marketing measurement) or lc (last-click) | Yes |
attribution_window | string | Attribution window, one of unlimited (no window), 1_days, 7_days or 30_days | Yes |
date | date | Date of the record | No |
source | string | UTM source where tracking is placed, for example facebook, tiktok, google or email | No |
medium | string | UTM medium indicating the traffic medium, for example cpc, organic, referral or email | No |
campaign_id | bigint | Unique identifier for the campaign | No |
campaign_name | string | Name of the advertising campaign | No |
adset_id | bigint | Unique identifier of the ad set | No |
adset_name | string | Name of the ad set | No |
ad_id | bigint | Unique identifier of the ad | No |
ad_name | string | Name of the ad | No |
campaign_status | string | Current status of the campaign, for example ACTIVE or PAUSED | No |
adset_status | string | Current status of the ad set, for example ACTIVE or PAUSED | No |
ad_status | string | Current status of the ad, for example ACTIVE or PAUSED | No |
ad_account_id | string | Identifier of the advertising account | No |
device_type | string | Type of device used, for example desktop, mobile or tablet | No |
os_family | string | Operating system family, for example Windows, iOS or Android | No |
device_brand | string | Brand of the device, for example Apple or Samsung | No |
ip_country | string | Country derived from the user IP address | No |
tracking_type | string | Type of tracking used, for example client-side or server-side | No |
custom_dimension_one | string | First custom dimension, configured per customer | No |
custom_dimension_two | string | Second custom dimension, configured per customer | No |
custom_dimension_three | string | Third custom dimension, configured per customer | No |
custom_dimension_four | string | Fourth custom dimension, configured per customer | No |
number_of_events | float | Total number of conversion events | No |
event_value | float | Total monetary value of conversion events | No |
returning_customers | float | Number of returning customers | No |
new_customers | float | Number of new customers | No |
returning_customer_revenue | float | Revenue from returning customers | No |
new_customer_revenue | float | Revenue from new customers | No |
gross_profit | float | Gross profit (ad spend is not subtracted) | No |
Media data (media_data)
Media spend and engagement metrics per client, campaign, ad set and ad, exactly as reported by the marketing channels. No attribution applied.
Field Name | Data Type | Description | Required |
data_share_id | bigint | Unique identifier used for your organisation in the share | Yes |
client_id | int | Unique identifier for a client in Billy Grace | Yes |
date | date | Date of the record | No |
source | string | Name of the source in the media data | No |
medium | string | Name of the marketing medium in the media data | No |
campaign_id | bigint | Unique identifier for the campaign | No |
campaign_name | string | Name of the advertising campaign | No |
adset_id | bigint | Unique identifier of the ad set | No |
adset_name | string | Name of the ad set | No |
ad_id | bigint | Unique identifier of the ad | No |
ad_name | string | Name of the ad | No |
campaign_status | string | Current status of the campaign, for example ACTIVE or PAUSED | No |
adset_status | string | Current status of the ad set, for example ACTIVE or PAUSED | No |
ad_status | string | Current status of the ad, for example ACTIVE or PAUSED | No |
ad_account_id | string | Identifier of the advertising account | No |
spend | float | Total advertising spend from the marketing channel | No |
clicks | int | Total number of clicks from the marketing channel | No |
impressions | int | Total number of ad impressions from the marketing channel | No |
frequency | float | Average number of times an ad was shown per user | No |
reach | int | Unique number of users who saw the ad at least once | No |
video_p25_watched | int | Number of times the video was watched to 25% | No |
video_p50_watched | int | Number of times the video was watched to 50% | No |
video_p75_watched | int | Number of times the video was watched to 75% | No |
completed_video_views | int | Number of times the video was watched to completion | No |
lead_gen | float | Total number of lead generation events | No |
Session data (session_data)
Session-level traffic data per client, combining UTM dimensions with device and geography breakdowns.
Field Name | Data Type | Description | Required |
data_share_id | bigint | Unique identifier used for your organisation in the share | Yes |
client_id | int | Unique identifier for a client in Billy Grace | Yes |
date | date | Date of the record | No |
source | string | UTM source where tracking is placed, for example facebook, tiktok, google or email | No |
medium | string | UTM medium indicating the traffic medium, for example cpc, organic, referral or email | No |
campaign_id | bigint | Unique identifier for the campaign | No |
campaign_name | string | Name of the advertising campaign | No |
adset_id | bigint | Unique identifier of the ad set | No |
adset_name | string | Name of the ad set | No |
ad_id | bigint | Unique identifier of the ad | No |
ad_name | string | Name of the ad | No |
campaign_status | string | Current status of the campaign, for example ACTIVE or PAUSED | No |
adset_status | string | Current status of the ad set, for example ACTIVE or PAUSED | No |
ad_status | string | Current status of the ad, for example ACTIVE or PAUSED | No |
ad_account_id | string | Identifier of the advertising account | No |
is_integrated_channel | int | Whether the channel has a marketing integration connected (1) or not (0) | No |
device_type | string | Type of device used, for example desktop, mobile or tablet | No |
os_family | string | Operating system family, for example Windows, iOS or Android | No |
device_brand | string | Brand of the device, for example Apple or Samsung | No |
ip_country | string | Country derived from the user IP address | No |
tracking_type | string | Type of tracking used, for example client-side or server-side | No |
pageviews | int | Total number of page views | No |
sessions | int | Total number of sessions | No |
new_users | int | Total number of first-time users | No |
Client dimension (client_dim)
A reference table with one row per client, useful for joining the tables above onto readable client names.
Field Name | Data Type | Description | Required |
id | int | Unique identifier for a client in Billy Grace, matches client_id in the other tables | Yes |
name | string | Name of the client | No |
timezone | string | Timezone configured for the client | No |
currency | string | Currency configured for the client | No |
Notes on the data
Attribution settings: daily_performance_data and conversion_data contain a row for every combination of attribution_model and attribution_window. Always filter to one of each; aggregating without doing so counts the same conversions multiple times.
Date type: the is_event_date flag marks whether a row is reported on the event date (1) or the session date (0). Filter to one value to avoid double counting.
Event type: conversion metrics are split per event in the ev column (e.g. purchase, lead). Filter or group on it when aggregating.
Spend metrics: spend, and anything derived from it such as ROAS or CPA, is only populated for channels with a paid marketing integration connected. Organic, direct and email sources return zero or null spend.
Platform vs. attributed data: media_data reflects the numbers as reported by the marketing channels themselves and carries no attribution fields. conversion_data and daily_performance_data contain conversions as attributed by Billy Grace.
Gross profit: the gross_profit metric does not subtract ad spend.
Sample queries (Token-based access only)
Once connected, you can read the share with plain Python or with Spark. See full md files for samples.
Python / pandas
load_as_pandas has no lazy plan, it downloads the whole result in one go. Filtering afterwards with normal pandas still means downloading every client's data first. Passing the filter as jsonPredicateHints instead pushes it to the share, so only that client's files are downloaded.
import json
import delta_sharing
PROFILE = "/path/to/config.share"
TABLE = "daily_performance_data"
CLIENT_ID = 1
client_filter = json.dumps({
"op": "equal",
"children": [
{"op": "column", "name": "client_id", "valueType": "int"},
{"op": "literal", "value": str(CLIENT_ID), "valueType": "int"},
],
})
performance_client = delta_sharing.load_as_pandas(
f"{PROFILE}#billy_grace.integrated.{TABLE}",
jsonPredicateHints=client_filter,
)
PySpark
import delta_sharing
from pyspark.sql import functions as F
PROFILE = "/path/to/config.share"
TABLE = "daily_performance_data"
CLIENT_ID = 1
performance = delta_sharing.load_as_spark(f"{PROFILE}#billy_grace.integrated.{TABLE}")
performance_client = performance.filter(F.col("client_id") == CLIENT_ID)
The data tables are partitioned by client_id, so filtering on it (as a predicate in pandas, or a normal .filter() in Spark) only downloads that client's files rather than the whole table. The share is read-only. If you want the data in your own storage, read it on a schedule and overwrite your copy each time. See sample implementation files for more details.
Additional resources
Delta sharing github: source and docs for the open-source Python and Spark connectors used above.
Databricks bearer token docs: Databricks' own guide to the Python, Spark, Power BI and Iceberg connectors for this exact model of sharing.
