Abstract

This document is the metadata contract for all-data-simulator/full_raw_data_simulator.py. It describes the source platform represented by each dataset, the generated CSV schema, field types and meanings, identity value, and differences between a real platform payload and this simulator’s flattened test representation.

Overview Flow

\begin{center} \small \setlength{\tabcolsep}{4pt} \begin{tabular}{c@{\quad}c@{\quad}c@{\quad}c@{\quad}c} \fcolorbox{black}{gray!10}{\parbox{0.22\linewidth}{\centering {Data sources}\[3pt] Meta Lead Ads\ TikTok Ads\ Google Analytics 4\ Zalo Official Account\ Adjust Pull API}} & & \fcolorbox{black}{gray!10}{\parbox{0.18\linewidth}{\centering {Fields}\[3pt] Identity fields\ Profile fields\ Event fields\ Campaign fields}} & & \fcolorbox{black}{gray!10}{\parbox{0.22\linewidth}{\centering {Identity Resolution}\[3pt] Normalize\ Match\ Merge customer identities}} \end{tabular} \end{center}

\newpage

1. Document Scope

Source datasets

DatasetSource platformGrain
meta_cir_api.csvMeta Lead AdsOne lead per row
tiktok_cir_api.csvTikTok AdsOne ad/reporting-day row
ga4_cir_api.csvGoogle Analytics 4One synthetic event/report row
zalo_cir_api.csvZalo Official AccountOne user profile row
adjust_cir_api.csvAdjustOne in-app event row

Generator index

GeneratorDataset
generate_meta_datameta_cir_api.csv
generate_tiktok_datatiktok_cir_api.csv
generate_ga4_dataga4_cir_api.csv
generate_zalo_datazalo_cir_api.csv
generate_adjust_dataadjust_cir_api.csv

Runtime and output metadata

ItemValue
Default row count20 rows per dataset
Shared identity count8 people, reused cyclically
Base date/time2026-08-01 09:00:00
Random seed42
CSV encodingutf-8-sig (UTF-8 with BOM)
CSV newline modenewline=""
Output directoryall-data-simulator/platform_cir_csv/
ZIP archiveplatform_cir_api_csv_simulated.zip under all-data-simulator/
ZIP contentsThe five generated CSV files, stored by basename
Missing dictionary keysIgnored by csv.DictWriter because extrasaction="ignore"

Relative output paths are resolved from the process working directory, not from the script directory. The documented command assumes the repository root is the working directory.

2. Shared Identity Metadata

PEOPLE is the synthetic identity source used to make cross-platform identity resolution possible. For row index i, each generator selects PEOPLE[i % len(PEOPLE)] except for TikTok, which is aggregate advertising data and does not use a person record.

AttributeTypeExamplePurpose
cidstringCUST-0001Synthetic customer key; appears in Adjust customer_user_id and JSON event_value
namestringNguyen AnFull display name for Meta and Zalo
firststringAnMeta lead first name
laststringNguyenMeta lead last name
emailstringan.nguyen@example.testMeta lead email; synthetic and non-deliverable
phonestring84901234001Meta/Zalo phone; digits are intentionally normalized-looking
citystringHanoiGeographic identity/context field
statestringHanoiGeographic identity/context field
countrystringVNISO-like country code used in platform rows
genderinteger1Zalo user gender simulation: code comments define 1 male, 2 female, 0 other/unknown

Identity linkage is synthetic. Real platform IDs are not used as a shared customer key. The strongest simulated CIR keys are email, phone, name, and the Adjust customer_user_id/event_value.customer_id pair.

\newpage

3. Meta Lead Ads Metadata

Source contract

A real Meta lead is an object. Form answers are commonly represented in a nested field_data collection. This simulator emits a flat CSV projection for ingestion and CIR testing.

Dataset metadata

ItemValue
Filemeta_cir_api.csv
GrainOne synthetic lead
RowsConfig.NUM_ROWS
Primary source identifierid
Identity fieldsfield_email, field_phone, field_first_name, field_last_name, field_city, field_state, field_country
Time fieldcreated_time
Time formatYYYY-MM-DDTHH:MM:SS+0000
FlatteningForm answers become field_* columns; campaign hierarchy is also flattened

Column metadata

ColumnTypeNullabilityMeaning and generation
idstringnon-nullSynthetic Meta lead object ID, formatted as 32800000000NNNN; simulator primary key
created_timestring datetimenon-nullConfig.BASE_DATE + i*4 hours + random minute, formatted with +0000 offset
form_idstringnon-nullFixed synthetic lead form ID 890000123456789
campaign_idstringnon-nullSynthetic campaign ID; random suffix from 1 to 4, so values can repeat
campaign_namestringnon-nullSynthetic campaign label; independently randomized from 1 to 4
adset_idstringnon-nullSynthetic ad set ID; random suffix from 1 to 5
adset_namestringnon-nullFixed synthetic ad set name Broad_Audience_18_65
ad_idstringnon-nullSynthetic ad ID; random suffix from 1 to 7
ad_namestringnon-nullSynthetic ad name; random creative suffix from 1 to 7
field_emailstring emailnon-nullEmail answer from the shared synthetic person; strongest Meta CIR key
field_phonestring phonenon-nullPhone answer from the shared synthetic person; strongest Meta CIR key after normalization
field_first_namestringnon-nullFirst-name form answer
field_last_namestringnon-nullLast-name form answer
field_citystringnon-nullCity form answer
field_statestringnon-nullState/province form answer
field_countrystring ISO-like codenon-nullCountry form answer, currently VN

Simulator limitations

  • field_* names are simulator column names, not a literal copy of a Meta response object’s nested field_data structure.
  • Campaign, ad set, and ad IDs are not guaranteed to be unique or stable by entity.
  • No Meta API permissions, access tokens, lead retrieval pagination, or webhook fields are represented.

\newpage

4. TikTok Integrated Reports Metadata

Source contract

TikTok reports contain dimensions and metrics. The simulator models an ad-level basic report grouped by day and country. The real API commonly returns numeric response values as strings in JSON; this CSV simulator writes Python numeric values, which the CSV serializer renders without quotes.

Dataset metadata

ItemValue
Filetiktok_cir_api.csv
GrainOne synthetic ad/reporting-day row
RowsConfig.NUM_ROWS
DimensionsAdvertiser, date, campaign, ad group, ad, country
MetricsImpressions, clicks, spend, CTR, CPC, CPM, conversions, conversion rate
Reporting datestat_time_day
Reporting date formatYYYY-MM-DD 00:00:00
CurrencyNot explicitly declared; spend is a synthetic account-currency amount

Column metadata

ColumnTypeNullabilityMeaning and generation
advertiser_idstringnon-nullFixed synthetic advertiser ID 710000123456789
stat_time_daystring datetimenon-nullConfig.BASE_DATE + (i % 10) days, normalized to midnight
campaign_idstringnon-nullSynthetic campaign ID; random suffix from 1 to 4
campaign_namestringnon-nullSynthetic campaign name; independently randomized from 1 to 4
adgroup_idstringnon-nullSynthetic ad group ID; random suffix from 1 to 5
adgroup_namestringnon-nullSynthetic ad group name; random suffix from 1 to 5
ad_idstringnon-nullSynthetic ad ID; random suffix from 1 to 7
ad_namestringnon-nullSynthetic ad name; random suffix from 1 to 7
country_codestring ISO-like codenon-nullRandom choice from VN, SG, and TH; VN has four entries and is therefore weighted
impressionsintegernon-nullRandom integer from 10,000 to 20,000
clicksintegernon-nullInteger truncation of impressions multiplied by a random rate from 1% to 4%
spenddecimalnon-nullRounded to two decimals; clicks multiplied by a random amount from 0.3 to 0.8
ctrdecimal percentnon-nullclicks / impressions * 100, rounded to four decimals
cpcdecimalnon-nullspend / clicks, rounded to four decimals; zero if clicks are zero
cpmdecimalnon-nullspend / impressions * 1000, rounded to four decimals
conversionintegernon-nullInteger truncation of clicks multiplied by a random rate from 1% to 5%
conversion_ratedecimal percentnon-nullconversion / clicks * 100, rounded to four decimals; zero if clicks are zero

Simulator limitations

  • The report request, access token, pagination, account timezone, account currency, and API response envelope are not represented.
  • Dimension IDs and names are independently randomized, so a repeated ID may receive different generated names across rows.
  • Metrics are synthetic estimates and should not be treated as platform benchmarks.

\newpage

5. Google Analytics 4 Metadata

Source contract

This dataset uses Google Analytics Data API dimension and metric names. It is a flat CSV projection of synthetic report rows, not a GA4 BigQuery export event record.

GA4 attribution and identity integration

UTM source and Facebook traffic

For a website, GA4 can read campaign parameters from the landing URL, including utm_source, utm_medium, utm_campaign, utm_id, utm_content, and utm_term. These values feed GA4 traffic-source dimensions such as sessionSource, sessionMedium, sessionCampaignName, and sessionCampaignId.

utm_source=facebook identifies Facebook as the traffic source; it does not identify the customer. Meta’s fbclid is a click identifier, not a customer ID, cid, or authenticated user identity. It must not be used as a CIR customer key. If the application retains it for internal campaign diagnostics, do not place PII in campaign parameters or page URLs, and apply the project’s privacy and retention rules.

Do not confuse these identifiers: GA4 client_id identifies a browser or app instance, GA4 user_id identifies a signed-in user with a non-PII site-owned value, fbclid identifies a Meta ad click, and the simulator’s cid identifies a synthetic customer.

The simulator now generates synthetic UTM fields and a Facebook-only fbclid as collection metadata. These values represent landing-page attribution inputs; they are not copied from a real URL or Facebook account.

Google SSO or internal login

After a successful Google SSO or internal login, the website may set GA4 user_id to a stable, site-owned, pseudonymous identifier. Google documents user_id as a reserved configuration value for connecting activity across sessions, devices, and platforms. The value must not itself be PII. It must not be sent as a custom user property, a custom dimension, or an event-level parameter.

Send user_id only while the user is authenticated. On logout, set it to null; do not send an empty string or the text "null". The simulator represents anonymous rows with empty user_id and authenticated rows with a synthetic non-PII value. It also includes synthetic client_id, user_pseudo_id, and login_method collection fields in the CSV.

Hashed email and phone

When a server-side integration uses GA4 Measurement Protocol, user-provided data can be sent in the top-level user_data object alongside user_id. Email and phone are not ordinary event parameters in this model. Measurement Protocol requires the developer to normalize the values, hash them with SHA-256, and send lowercase hex-encoded values in sha256_email_address and sha256_phone_number.

The documented normalization rules include:

  • Email: remove leading/trailing whitespace, lowercase, remove spaces, and remove periods before the domain for gmail.com or googlemail.com addresses, then hash.
  • Phone: remove all non-digit characters, add the + prefix using E.164-style form, then hash.

Only send this data when the required consent, privacy, and data-governance conditions for the implementation are satisfied. Never send raw email or phone in a GA4 URL, ordinary event parameter, or custom dimension. The simulator CSV contains only synthetic SHA-256 fixture values in the sha256_* columns; it does not contain raw email or phone.

Illustrative Measurement Protocol shape:

{
  "client_id": "WEB_CLIENT_ID",
  "user_id": "NON_PII_INTERNAL_USER_ID",
  "events": [{"name": "login", "params": {"method": "google_sso"}}],
  "user_data": {
    "sha256_email_address": ["SHA256_EMAIL_HEX"],
    "sha256_phone_number": ["SHA256_PHONE_HEX"]
  }
}

The example values are placeholders. The actual request also requires the appropriate Measurement Protocol transport credentials and identifiers.

Dataset metadata

ItemValue
Filega4_cir_api.csv
GrainOne synthetic event/report row
RowsConfig.NUM_ROWS
Date fielddate
Date formatYYYYMMDD
Event setpage_view, view_item, begin_checkout, purchase
Source setgoogle, facebook, tiktok, zalo
Revenue currencyNot explicitly declared; values are synthetic VND-like amounts
Key-event modelpurchase produces keyEvents = 1; all other events produce 0
Authentication modelEvery third row is anonymous; other rows use synthetic google_sso or internal login context
UTM modelutm_* values are synthetic and aligned with the session/campaign fields
User data modelAuthenticated rows contain synthetic SHA-256 email/phone values; raw PII is never generated

Column metadata

ColumnTypeNullabilityMeaning and generation
datestring datenon-nullRandom date from base date through 10 days later, formatted YYYYMMDD
eventNamestring enum-likenon-nullRandom synthetic event from the four-event set
campaignIdstringnon-nullSynthetic GAD-C360-NNN ID, random suffix from 1 to 4
campaignNamestringnon-nullSynthetic web campaign name, independently randomized from 1 to 4
sessionSourcestring enum-likenon-nullRandom choice from google, facebook, tiktok, zalo
sessionMediumstring enum-likenon-nullIntended to be cpc for Google and paid_social otherwise; current implementation compares the source list rather than the selected source, so it currently emits paid_social for every row
countrystring ISO-like codenon-nullShared synthetic person’s country, currently VN
citystringnon-nullShared synthetic person’s city
browserstring enum-likenon-nullRandom choice from Chrome, Safari, Edge
deviceCategorystring enum-likenon-nullRandom choice from mobile, desktop, tablet
platformstring enum-likenon-nullFixed web
sessionCampaignIdstringnon-nullSame generated value as campaignId
sessionCampaignNamestringnon-nullSynthetic session campaign name; independently randomized from 1 to 4
transactionIdstringempty for non-purchaseORD-NNNNN for purchase rows; empty string otherwise
eventCountintegernon-nullRandom integer from 1 to 5
keyEventsintegernon-null1 for purchase rows and 0 otherwise; modern GA4 metric naming
totalRevenuedecimalnon-nullRandom 450,000 to 950,000 for purchase rows; 0 otherwise
engagementRatedecimal fractionnon-nullRandom fraction from 0.35 to 0.85; follows GA4 fraction convention
client_idstringnon-nullSynthetic browser/app collection identifier, unique per generated row; not a customer ID
user_pseudo_idstringnon-nullSynthetic pseudonymous GA4 collection identifier, unique per generated row
user_idstringempty for anonymous rowsSynthetic non-PII site-owned identifier GA4-CUST-NNNN for authenticated rows
login_methodstringempty for anonymous rowsSynthetic authentication context: google_sso or internal
utm_sourcestringnon-nullSynthetic landing attribution source; equal to sessionSource
utm_mediumstringnon-nullSynthetic landing attribution medium; equal to sessionMedium, cpc for Google and paid_social otherwise
utm_campaignstringnon-nullSynthetic landing campaign name; equal to campaignName and sessionCampaignName
utm_idstringnon-nullSynthetic landing campaign ID; equal to campaignId and sessionCampaignId
fbclidstringempty except Facebook rowsSynthetic Meta click identifier when utm_source is facebook; never a customer key
sha256_email_addressstring SHA-256 hexempty for anonymous rowsNormalized synthetic email hashed as lowercase hexadecimal SHA-256 for Measurement Protocol-style user data
sha256_phone_numberstring SHA-256 hexempty for anonymous rowsDigits-only synthetic phone normalized with +, then hashed as lowercase hexadecimal SHA-256

Simulator limitations

  • sessionSource is not linked to a real session or user identifier.
  • sessionCampaignName and campaignName are not guaranteed to correspond to their respective IDs.
  • There is no userPseudoId, session ID, event timestamp, item array, user property, ecommerce item, or GA4 request/response envelope.
  • client_id, user_pseudo_id, user_id, UTM fields, fbclid, and flattened sha256_* fields are simulator collection metadata; they are not all queryable as standard Google Analytics Data API dimensions.
  • totalRevenue has no declared currency in this file.
  • The sessionMedium implementation currently has a semantic defect documented above; consumers should not infer source-medium correctness from generated rows until fixed.

\newpage

6. Zalo Official Account Metadata

Source contract

The current Zalo OA model is the v3.0 User Detail operation. A real response contains nested shared-information data. This dataset flattens selected profile and shared-info attributes into CSV columns.

Dataset metadata

ItemValue
Filezalo_cir_api.csv
GrainOne synthetic Zalo user profile
RowsConfig.NUM_ROWS
Primary source identifieruser_id
Identity fieldsdisplay_name, shared_info_name, shared_info_phone, shared_info_city, shared_info_address
Privacy/sensitivity fieldsis_sensitive, user_is_follower
Flatteningshared_info_* columns represent values extracted from a real shared_info object

Column metadata

ColumnTypeNullabilityMeaning and generation
user_idstring integernon-nullSynthetic Zalo user ID, base 567826391599986760 plus row index
user_id_by_appstring integernon-nullSynthetic app-scoped user ID, base 567826390000000000 plus row index
display_namestringnon-nullShared synthetic person’s full name
user_genderinteger enum-likenon-nullShared person’s gender code; code comments define 1 male, 2 female, 0 other/unknown
is_sensitivebooleannon-nullFixed False; represents whether returned profile data is sensitive
user_is_followerbooleannon-nullFixed True; represents follower status
shared_info_namestringnon-nullFlattened name from the conceptual shared_info object
shared_info_phonestring phonenon-nullFlattened phone from the conceptual shared_info object; CIR identity field
shared_info_citystringnon-nullFlattened city from the conceptual shared_info object
shared_info_addressstringnon-nullSynthetic Sample street N, city address
tags_and_notes_infostring enum-likenon-nullSynthetic label from four Vietnamese-language tag values; not a documented profile identity field

Simulator limitations

  • The CSV is not the raw JSON response and does not preserve the shared_info object.
  • tags_and_notes_info is simulator-specific enrichment, not part of the documented user identity projection described here.
  • Real Zalo permissions, access tokens, follower authorization, privacy behavior, and response error envelopes are not represented.
  • Zalo documentation is rendered through a JS-heavy portal; verify exact response fields against live v3.0 response examples before treating this CSV as an integration fixture.

\newpage

7. Adjust Pull API Raw-Data Metadata

Source contract

Adjust raw-data reports use a broad, report-dependent schema. Fields can be empty or unavailable depending on report type, platform, attribution source, privacy settings, and delivery method. This simulator models an in-app-event report with a selected set of canonical Pull API field names.

Dataset metadata

ItemValue
Fileadjust_cir_api.csv
GrainOne synthetic Adjust in-app event
RowsConfig.NUM_ROWS
Identity fieldscustomer_user_id, JSON event_value.customer_id, device identifiers
Event setadj_login, adj_content_view, adj_add_to_cart, adj_purchase
Time formatYYYY-MM-DD HH:MM:SS without an explicit timezone
Event value formatJSON string; purchase rows include customer_id and order_id
Revenue currencyFixed VND for rows with synthetic revenue

Column metadata

ColumnTypeNullabilityMeaning and generation
attributed_touch_typestring enum-likenon-nullRandom click or impression; attribution engagement type
attributed_touch_timestring datetimenon-nullInstall time minus a random 5 to 60 minutes
install_timestring datetimenon-nullBase date plus random 0 to 5 days and 1 to 12 hours
event_timestring datetimenon-nullInstall time plus random 5 to 120 minutes
event_namestring enum-likenon-nullRandom Adjust event name from the four-event set
event_valuestring JSONnon-nullJSON containing customer_id; purchase rows also contain order_id
event_revenuedecimalnon-nullRandom 100,000 to 500,000 for purchase rows; 0 otherwise
event_revenue_currencystring currency codenon-nullFixed VND
event_sourcestring enum-likenon-nullFixed SDK
media_sourcestring enum-likenon-nullRandom facebook, tiktok, googleadwords_int, or zalo
channelstringnon-nullRandom display label: Facebook Ads, TikTok Ads, Google Ads, or Zalo
campaignstringnon-nullSynthetic campaign name; random suffix from 1 to 4
campaign_idstringnon-nullSynthetic Adjust campaign ID ADJ-CAMP-NNN
adsetstringnon-nullSynthetic ad set name; random suffix from 1 to 5
adset_idstringnon-nullSynthetic ad set ID ADJ-AS-NNN
adstringnon-nullSynthetic creative name; random suffix from 1 to 7
ad_idstringnon-nullSynthetic ad ID ADJ-AD-NNN
country_codestring ISO-like codenon-nullShared person’s country, currently VN
statestringnon-nullShared person’s state/province
citystringnon-nullShared person’s city
postal_codestringnon-nullSynthetic six-digit-looking postal code from 700010 to 700099
ipstring IPv4-likenon-nullSynthetic IPv4-like address beginning 103.21.
operatorstringnon-nullRandom Viettel, MobiFone, or VinaPhone; Adjust field dictionary name used by current code
languagestring BCP-47-likenon-nullFixed vi
adjust_idstringnon-nullSynthetic SDK-generated-looking ID; random two-digit segment means uniqueness is not guaranteed
advertising_idstring UUID-likenon-nullSynthetic resettable advertising ID; row-index suffix makes this simulator-unique
idfastringempty on AndroidSynthetic iOS advertising identifier; empty when is_android is true
android_idstringempty on iOSSynthetic Android identifier; empty when is_android is false
customer_user_idstringnon-nullShared synthetic cid, strongest Adjust-to-CIR key
idfvstringempty on AndroidSynthetic iOS vendor identifier; empty when is_android is true
platformstring enum-likenon-nullandroid or ios, selected by is_android
device_typestringnon-nullSynthetic device model label; Adjust field dictionary notes this field is deprecated/unpopulated in favor of device model in current reports
os_versionstringnon-nullRandom Android 14/15 or iOS 17.6/16.7
app_versionstringnon-nullFixed 6.8.1
sdk_versionstringnon-nullFixed 6.15.0
app_idstringnon-nullFixed synthetic app ID com.example.customer360
bundle_idstringnon-nullFixed synthetic bundle/app ID com.example.customer360
user_agentstringnon-nullSynthetic Android or iOS browser-style user agent
http_referrerstring URLnon-nullFixed synthetic landing URL
original_urlstring URLnon-nullSynthetic app URL containing the person’s cid

Simulator limitations

  • This is a selected subset of the Adjust main schema, not a complete raw-data field dictionary export.
  • The timestamp strings omit timezone information even though delivery method and account settings affect real Adjust timestamp timezone behavior.
  • Attribution hierarchy values are independently randomized and are not a stable campaign entity model.
  • adjust_id can collide because only a limited random suffix is used; do not use it as a guaranteed unique key in tests.
  • Device identifiers are synthetic and must not be interpreted as real device identity.

8. Cross-Platform CIR Metadata

Identity key availability

PlatformStrongest shared keySecondary keysDirect cid column?
Metafield_email, field_phoneFirst/last name, city, stateNo
TikTokNoneAdvertiser/campaign hierarchy and country onlyNo
GA4None in current schema; production GA4 may use non-PII user_idCity, country, campaign/source context, optional UTM-derived traffic dimensionsNo
Zaloshared_info_phoneName, city, addressNo
Adjustcustomer_user_id, event_value.customer_idOriginal URL, device identifiers, geographyYes, embedded in fields rather than as a column

Expected synthetic row-to-person mapping

  • Meta, GA4, Zalo, and Adjust select shared people cyclically.
  • With 20 rows and 8 people, person positions repeat after every eight rows.
  • TikTok rows are aggregate advertising observations and intentionally have no person-level identity.
  • A real CIR implementation should normalize email and phone before matching and should treat names, city, and device identifiers as supporting evidence rather than guaranteed unique identifiers.

Data quality and reproducibility

  • The module seeds Python’s global random generator with 42 at import time.
  • Importing this module has side effects: it creates the configured output directory and changes the process-global random sequence.
  • Reproducibility assumes the same Python implementation, execution order, configuration, and generator code.
  • CSV values are serialized from Python values; downstream ingestion should explicitly cast numeric, boolean, date, datetime, and JSON-string fields instead of relying on inference.

9.