{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Setup\n",
    "# Install the required package\n",
    "# %pip install requests dotenv\n",
    "# %pip install dotenv\n",
    "# %pip install --upgrade ShopifyAPI\n",
    "\n",
    "# Import necessary libraries\n",
    "from klaviyo_api import KlaviyoAPI\n",
    "from dotenv import dotenv_values\n",
    "from datetime import datetime, timedelta\n",
    "import time\n",
    "import requests\n",
    "import json\n",
    "import pprint\n",
    "import imp\n",
    "import pandas as pd\n",
    "import sqlite3\n",
    "import api\n",
    "imp.reload(api)\n",
    "from api import BigApi\n",
    "\n",
    "BigApi.init(\"../.env\")\n",
    "# BigApi.adminLogin()  # only needed if accessing Bigscreen backend\n",
    "\n",
    "config = dotenv_values(\"../.env\")\n",
    "KLAVIYO_API_KEY = config['KLAVIYO_API_KEY']\n",
    "\n",
    "klaviyo = KlaviyoAPI(KLAVIYO_API_KEY, max_delay=60, max_retries=3, test_host=None)\n",
    "\n",
    "klaviyo_skip_profile_ids = []\n",
    "incrementing_page_size = 0\n",
    "page_cursor = ''\n",
    "page = 0\n",
    "\n",
    "\n",
    "# Get metric_id for \"Fulfilled Order\"\n",
    "metrics_response = klaviyo.Metrics.get_metrics()\n",
    "for metric in metrics_response.data:\n",
    "    if metric.attributes.name == 'Fulfilled Order':\n",
    "        fulfilled_order_metric_id = metric.id\n",
    "    if metric.attributes.name == 'Fulfilled Partial Order':\n",
    "        fulfilled_partial_order_metric_id = metric.id\n",
    "    if 'fulfilled_order_metric_id' in locals() and 'fulfilled_partial_order_metric_id' in locals():\n",
    "        break\n",
    "else:\n",
    "    raise ValueError(\"Metrics 'Fulfilled Order' and 'Fulfilled Partial Order' not found\")\n",
    "\n",
    "\n",
    "def pprint_klaviyo(response, propsFilter=[]):\n",
    "  # iterate through the properties of response.data[0] and print them\n",
    "  for key, value in response.data[0]:\n",
    "      # for the 'relationships' property, just print \"[...]\" to avoid printing too much\n",
    "      # for the 'attributes' property, print the key-value pairs\n",
    "      if key == 'relationships':\n",
    "          print(f\"{key}: [...]\")\n",
    "      elif key == 'attributes':\n",
    "          print(f\"{key}:\")\n",
    "          for attr_key, attr_value in value:\n",
    "              # for the 'properties' attribute, print the key-value pairs\n",
    "              if attr_key == 'properties':\n",
    "                  print(f\"  {attr_key}:\")\n",
    "                  for prop_key, prop_value in attr_value.items():\n",
    "                      if(not len(propsFilter) or prop_key in propsFilter):\n",
    "                          # for specific properties, print the key-value pair\n",
    "                          if isinstance(prop_value, dict):\n",
    "                              # if the property value is a dictionary, print it in a formatted way\n",
    "                              print(f\"    {prop_key}: {json.dumps(prop_value, indent=2)}\")\n",
    "                          else:\n",
    "                              # otherwise, print the key-value pair directly\n",
    "                              print(f\"    {prop_key}: {prop_value}\")\n",
    "              else:\n",
    "                  # for other attributes, print the key-value pair directly\n",
    "                  print(f\"  {attr_key}: {attr_value}\")\n",
    "      else:\n",
    "          # for other properties, print the key-value pair directly\n",
    "          print(f\"{key}: {value}\")\n",
    "\n",
    "\n",
    "def get_next_page_size(items_count, max_items, default_page_size=100):\n",
    "    next_page_size = default_page_size\n",
    "    if (items_count + default_page_size) > max_items:\n",
    "        next_page_size = max_items % default_page_size\n",
    "    return next_page_size\n",
    "\n",
    "\n",
    "# Retrieve all profiles from a given Klaviyo segment and bulk create events for those profiles\n",
    "def bulk_create_events_for_segment(segment_id, event_name, event_properties, max_profiles=1000):\n",
    "  EVENT_CHECK_INTERVAL = 0.8  # seconds\n",
    "  fields_profile = ['email', 'properties']\n",
    "  profiles_list = []\n",
    "  page_cursor = ''\n",
    "  page = 0\n",
    "  ready = False\n",
    "\n",
    "  # Retrieve profiles from the segment\n",
    "  while not ready and len(profiles_list) < max_profiles:\n",
    "    page += 1\n",
    "    next_page_size = get_next_page_size(len(profiles_list), max_profiles)\n",
    "    print(f\"Requesting {next_page_size} profiles from segment {segment_id}. Page #{page} cursor: {page_cursor}\")\n",
    "    response = klaviyo.Segments.get_profiles_for_segment(segment_id, fields_profile=fields_profile, page_size=next_page_size, page_cursor=page_cursor)\n",
    "    if fields_profile and len(fields_profile) > 0:\n",
    "      profiles_list.extend(response['data'])\n",
    "    else:\n",
    "      profiles_list.extend(response.data)\n",
    "    page_cursor = response.get('links', {}).get('next', None)\n",
    "    if page_cursor is None:\n",
    "      ready = True\n",
    "    time.sleep(EVENT_CHECK_INTERVAL)\n",
    "\n",
    "  print(f\"Retrieved {len(profiles_list)} profiles from segment {segment_id}.\")\n",
    "\n",
    "  # Prepare events for bulk creation\n",
    "  event_upserts = []\n",
    "  for index, profile in enumerate(profiles_list):\n",
    "    if index >= max_profiles:\n",
    "      print(f\"Reached maximum of {max_profiles} profiles for this run. Run again to process more.\")\n",
    "      break\n",
    "    event_upserts.append({\n",
    "      \"type\": \"event-bulk-create\",\n",
    "      \"attributes\": {\n",
    "        \"profile\": {\n",
    "          \"data\": {\n",
    "            \"type\": \"profile\",\n",
    "            \"attributes\": {\n",
    "              \"email\": profile['attributes'].get('email')\n",
    "            }\n",
    "          }\n",
    "        },\n",
    "        \"events\": {\n",
    "          \"data\": [\n",
    "            {\n",
    "              \"type\": \"event\",\n",
    "              \"attributes\": {\n",
    "                \"properties\": event_properties,\n",
    "                \"metric\": {\n",
    "                  \"data\": {\n",
    "                    \"type\": \"metric\",\n",
    "                    \"attributes\": {\n",
    "                      \"name\": event_name\n",
    "                    }\n",
    "                  }\n",
    "                }\n",
    "              }\n",
    "            }\n",
    "          ]\n",
    "        }\n",
    "      }\n",
    "    })\n",
    "    if len(event_upserts) % 100 == 0:\n",
    "      print(f\"Prepared {len(event_upserts)} events so far.\")\n",
    "\n",
    "  # Bulk create events\n",
    "  if event_upserts:\n",
    "    bulk_events_body = {\n",
    "      'data': {\n",
    "        'type': 'event-bulk-create-job',\n",
    "        'attributes': {\n",
    "          'events-bulk-create': {\n",
    "            'data': event_upserts\n",
    "          }\n",
    "        }\n",
    "      }\n",
    "    }\n",
    "    print(f\"Arranging bulk \\\"{event_name}\\\" event creation for {len(event_upserts)} profiles...\")\n",
    "    response = klaviyo.Events.bulk_create_events(bulk_events_body)\n",
    "    print(\"Bulk event creation response:\")\n",
    "    pprint.pprint(response, indent=2)\n",
    "  else:\n",
    "    print(\"No events to create.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# misc python test\n",
    "max_items = 334\n",
    "default_page_size = 100\n",
    "items_count = 0\n",
    "i = 0\n",
    "\n",
    "while items_count < max_items:\n",
    "# while i <= 0:\n",
    "  i += 1\n",
    "  next_page_size = get_next_page_size(items_count, max_items, default_page_size)\n",
    "  items_count += next_page_size\n",
    "  print(f\"Iteration {i}: {items_count} items (page size: {next_page_size})\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Use pandas to read VRChatCodes.csv and use its \"Code\" column to populate rows into a new SQLite database table with columns: code, assigned_to, assigned_timestamp\n",
    "df = pd.read_csv('VRChatCodes.csv')\n",
    "print(df.head())\n",
    "print(df.columns)\n",
    "codes = df['Code'].tolist()\n",
    "print(f\"Read {len(codes)} codes from CSV\")\n",
    "\n",
    "conn = sqlite3.connect('vrchat_codes.db')\n",
    "c = conn.cursor()\n",
    "c.execute('''CREATE TABLE IF NOT EXISTS codes\n",
    "             (code TEXT PRIMARY KEY, assigned_to TEXT, assigned_timestamp TEXT)''')\n",
    "for code in codes:\n",
    "    try:\n",
    "        c.execute(\"INSERT INTO codes (code) VALUES (?)\", (code,))\n",
    "    except sqlite3.IntegrityError:\n",
    "        pass  # ignore duplicate codes\n",
    "conn.commit()\n",
    "conn.close()\n",
    "print(\"Database populated with codes\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Add a new column \"event_triggered_timestamp\" to the table if it doesn't exist\n",
    "conn = sqlite3.connect('vrchat_codes.db')\n",
    "c = conn.cursor()\n",
    "c.execute(\"PRAGMA table_info(codes)\")\n",
    "columns = [info[1] for info in c.fetchall()]\n",
    "if 'event_triggered_timestamp' not in columns:\n",
    "    c.execute(\"ALTER TABLE codes ADD COLUMN event_triggered_timestamp TEXT\")\n",
    "    print(\"Added column 'event_triggered_timestamp' to the table\")\n",
    "conn.commit()\n",
    "conn.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Clear all cells for column \"event_triggered_timestamp\"\n",
    "conn = sqlite3.connect('vrchat_codes.db')\n",
    "c = conn.cursor()\n",
    "c.execute(\"UPDATE codes SET event_triggered_timestamp = NULL\")\n",
    "conn.commit()\n",
    "conn.close()\n",
    "print(\"Cleared all cells in column 'event_triggered_timestamp'\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Output table info\n",
    "conn = sqlite3.connect('vrchat_codes.db')\n",
    "c = conn.cursor()\n",
    "\n",
    "# get column headers from the table and print\n",
    "c.execute(\"PRAGMA table_info(codes)\")\n",
    "columns = [info[1] for info in c.fetchall()]\n",
    "print(\"Column headers:\", columns)\n",
    "\n",
    "# get first 8 rows from the table and print\n",
    "print(\"First 8 rows:\")\n",
    "c.execute(\"SELECT * FROM codes LIMIT 8\")\n",
    "rows = c.fetchall()\n",
    "for row in rows:\n",
    "    print(row)\n",
    "\n",
    "# print total number of rows\n",
    "c.execute(\"SELECT COUNT(*) FROM codes\")\n",
    "count = c.fetchone()[0]\n",
    "print(f\"Total number of rows in the database table: {count}\")\n",
    "\n",
    "conn.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# TOOL: Claim a single code, or fetch it if already claimed\n",
    "claim_email = 'nate@bigscreenvr.com'\n",
    "\n",
    "conn = sqlite3.connect('vrchat_codes.db')\n",
    "c = conn.cursor()\n",
    "\n",
    "c.execute(f\"SELECT code FROM codes WHERE assigned_to IS '{claim_email}' LIMIT 1\") \n",
    "row = c.fetchone()\n",
    "if row is not None:\n",
    "  print(f\"A code is already claimed for {claim_email}: \", row[0])\n",
    "  # output dates\n",
    "  c.execute(\"SELECT assigned_timestamp, event_triggered_timestamp FROM codes WHERE assigned_to IS ?\", (claim_email,))\n",
    "  row = c.fetchone()\n",
    "  print(f\"  assigned_timestamp: {row[0]}\")\n",
    "  print(f\"  event_triggered_timestamp: {row[1]}\")\n",
    "else:\n",
    "  c.execute(\"SELECT code FROM codes WHERE assigned_to IS NULL LIMIT 1\")\n",
    "  row = c.fetchone()\n",
    "  if row is None:\n",
    "    print(\"No more unassigned codes available in the database. Stopping.\")\n",
    "    exit()\n",
    "  vrce_code = row[0]\n",
    "  c.execute(\"UPDATE codes SET assigned_to = ?, assigned_timestamp = ? WHERE code = ?\", (claim_email, datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"), vrce_code))\n",
    "  print(f\"Claimed code {vrce_code} for {claim_email}.\")\n",
    "  conn.commit()\n",
    "\n",
    "conn.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Assign codes to all profiles in segment \"VRCE Buyers - Code Not Generated\"\n",
    "BULK_IMPORT_PROFILES_MAX = 10000 #Klaviyo API limit\n",
    "PAGE_SIZE_INCREMENT = 100\n",
    "EVENT_CHECK_INTERVAL = 0.8  # seconds\n",
    "brandon_test_seg = 'RyVhYy'\n",
    "vrce_buyers_need_code_seg = 'X8CWen'\n",
    "vrce_upgraders_need_code_seg = 'VgpXba'\n",
    "target_seg = vrce_upgraders_need_code_seg\n",
    "fields_profile = ['email', 'properties']\n",
    "profiles_list = []\n",
    "profiles_with_vrce_code_set = 0\n",
    "next_page_size = 100\n",
    "\n",
    "\n",
    "conn = sqlite3.connect('vrchat_codes.db')\n",
    "c = conn.cursor()\n",
    "\n",
    "\n",
    "### ONE PAGE PER RUN ###\n",
    "# page += 1\n",
    "# print(f\"Getting {page_size} profiles from the target segment. Page #{page} cursor: {page_cursor}\")\n",
    "# response = klaviyo.Segments.get_profiles_for_segment(target_seg, fields_profile=fields_profile, page_size=page_size, page_cursor=page_cursor)\n",
    "# page_cursor = response.get('links', {}).get('next', None)\n",
    "# print (f\"Next page cursor: {page_cursor}\")\n",
    "# # pprint.pprint(response, indent=2)\n",
    "# if(fields_profile != None and len(fields_profile) > 0):\n",
    "#   profiles_list = response['data']\n",
    "# else:\n",
    "#   profiles_list = response.data\n",
    "# # profiles_list = [profiles_list[0]]  # debug\n",
    "\n",
    "\n",
    "### ALL PAGES IN ONE RUN ###\n",
    "page = 0\n",
    "page_cursor = ''\n",
    "ready = False\n",
    "while not ready and len(profiles_list) < BULK_IMPORT_PROFILES_MAX:\n",
    "    page += 1\n",
    "    next_page_size = get_next_page_size(len(profiles_list), BULK_IMPORT_PROFILES_MAX, PAGE_SIZE_INCREMENT)\n",
    "    print(f\"Requesting {next_page_size} more profiles from the target segment. Page #{page} cursor: {page_cursor}\")\n",
    "    response = klaviyo.Segments.get_profiles_for_segment(target_seg, fields_profile=fields_profile, page_size=next_page_size, page_cursor=page_cursor)\n",
    "    if(fields_profile != None and len(fields_profile) > 0):\n",
    "      profiles_list.extend(response['data'])\n",
    "    else:\n",
    "      profiles_list.extend(response.data)\n",
    "    page_cursor = response.get('links', {}).get('next', None)\n",
    "    # print (f\"Next page cursor: {page_cursor}\") #debug\n",
    "    if page_cursor == None:\n",
    "        ready = True\n",
    "    # wait 0.5 sec to avoid hitting rate limits\n",
    "    time.sleep(EVENT_CHECK_INTERVAL)\n",
    "\n",
    "\n",
    "profile_upserts = []\n",
    "for index, profile in enumerate(profiles_list):\n",
    "    profile_id = profile['id']\n",
    "    if 'properties' in profile['attributes'] and 'vrchat_edition_code' in profile['attributes']['properties']:\n",
    "        print(f\"Profile {profile_id} already has vrchat_edition_code set. Skipping...\")\n",
    "        time.sleep(EVENT_CHECK_INTERVAL)\n",
    "        continue  # Skip profiles that already have et_token_shared set to True\n",
    "    # print(f\"Setting et_token_shared to True for profile {index+1} of {len(profiles_list)} ({profile_id})\")  # debug\n",
    "    # time.sleep(EVENT_CHECK_INTERVAL)  # debug\n",
    "\n",
    "    # set vrce_code to the first unassigned code from the database and mark it as assigned, with assigned_to set to the profile's email and assigned_timestamp set to the current timestamp\n",
    "    c.execute(\"SELECT code FROM codes WHERE assigned_to IS NULL LIMIT 1\")\n",
    "    row = c.fetchone()\n",
    "    if row is None:\n",
    "        print(\"No more unassigned codes available in the database. Stopping.\")\n",
    "        break\n",
    "    vrce_code = row[0]\n",
    "    c.execute(\"UPDATE codes SET assigned_to = ?, assigned_timestamp = ? WHERE code = ?\", (profile['attributes'].get('email', profile_id), datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"), vrce_code))\n",
    "    conn.commit()\n",
    "\n",
    "    profile_upserts.append({\n",
    "        'type': 'profile',\n",
    "        'id': profile_id,\n",
    "        'attributes': {\n",
    "            'properties': {\n",
    "                'vrchat_edition_code': vrce_code\n",
    "            }\n",
    "        }\n",
    "    })\n",
    "    profiles_with_vrce_code_set += 1\n",
    "    if len(profile_upserts) % 100 == 0:\n",
    "        print(f\"Prepared {len(profile_upserts)} profiles so far. Processing...\")\n",
    "    \n",
    "if profiles_with_vrce_code_set == 0:\n",
    "    print(\"No profiles to update vrchat_edition_code property.\")\n",
    "else:\n",
    "    update_profiles_body = {\n",
    "        'data': {\n",
    "            'type': 'profile-bulk-import-job',\n",
    "            'attributes': {\n",
    "              'profiles': {\n",
    "                'data': profile_upserts\n",
    "              }\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "\n",
    "    print(f\"Arranging bulk assignment of vrchat_edition_code for {profiles_with_vrce_code_set} profiles...\")\n",
    "    response = klaviyo.Profiles.bulk_import_profiles(update_profiles_body)\n",
    "    print(f\"Done. Response:\")\n",
    "    pprint.pprint(response, indent=2)\n",
    "    conn.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Check status of bulk profile import job\n",
    "job_id = \"VkFENDhOX21haW50ZW5hbmNlLnVjQzJGYS4xNzYwMDQ1MzM0LkowTGVKag\"\n",
    "\n",
    "def get_bulk_import_status(job_id):\n",
    "    try:\n",
    "        # Get the bulk profile import job status\n",
    "        response = klaviyo.Profiles.get_bulk_import_profiles_job(job_id)\n",
    "        \n",
    "        # Extract relevant information from the response\n",
    "        job_data = response.data\n",
    "        attributes = job_data.attributes\n",
    "        # pprint.pprint(response, indent=2)\n",
    "        \n",
    "        # Print job status and relevant details\n",
    "        print(f\"Job ID: {job_data.id}\")\n",
    "        print(f\"Status: {attributes.status}\")\n",
    "        print(f\"Created At: {attributes.created_at}\")\n",
    "        # print(f\"Updated At: {attributes.updated_at}\")\n",
    "        print(f\"Total Profiles: {attributes.total_count}\")\n",
    "        print(f\"Completed Profiles: {attributes.completed_count}\")\n",
    "        print(f\"Failed Profiles: {attributes.failed_count}\")\n",
    "        \n",
    "        return response\n",
    "    \n",
    "    except Exception as e:\n",
    "        print(f\"Error retrieving job status: {str(e)}\")\n",
    "        return None\n",
    "\n",
    "get_bulk_import_status(job_id)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Bulk event creation for given email addresses\n",
    "EVENTS_MAX = 1000 #Klaviyo API limit\n",
    "EVENT_NAME = \"VRChat Edition Code Assigned\"\n",
    "EVENT_CHECK_INTERVAL = 0.8  # seconds\n",
    "profiles_list = [ #debug\n",
    "  {'email': 'jeppevinkel@gmail.com', 'code': '2PEEXDS924T0EW1A'},\n",
    "]\n",
    "target_emails = [\n",
    "  # \"laxy.vrc@gmail.com\",\n",
    "]\n",
    "\n",
    "\n",
    "EXCLUDE_PREVIOUSLY_TRIGGERED = True  # only include profiles that haven't had this event triggered before\n",
    "CHECK_ALL = True  # check all profiles in the database, ignoring EVENTS_MAX limit\n",
    "DEBUG_MODE = True\n",
    "\n",
    "\n",
    "conn = sqlite3.connect('vrchat_codes.db')\n",
    "c = conn.cursor()\n",
    "if not DEBUG_MODE:\n",
    "  # derive profiles_list from the table (values assigned_to and code)\n",
    "  query = \"SELECT assigned_to, code FROM codes WHERE assigned_to IS NOT NULL\"\n",
    "  if EXCLUDE_PREVIOUSLY_TRIGGERED:\n",
    "    query += \" AND event_triggered_timestamp IS NULL\"\n",
    "  if not CHECK_ALL:\n",
    "    query += \" LIMIT ?\"\n",
    "    c.execute(query, (EVENTS_MAX,))\n",
    "  else:\n",
    "    c.execute(query)\n",
    "  rows = c.fetchall()\n",
    "  profiles_list = [{'email': row[0], 'code': row[1]} for row in rows]\n",
    "  # remove profiles whose email is not in target_emails (if target_emails is not empty)\n",
    "  if len(target_emails) > 0:\n",
    "    profiles_list = [profile for profile in profiles_list if profile['email'] in target_emails]\n",
    "  print(f\"Found {len(profiles_list)} profiles (limit {EVENTS_MAX}) with assigned codes in the database.\")\n",
    "  # print the first 8 profiles (DEBUG)\n",
    "  # print(\"First 8 profiles:\")\n",
    "  # for profile in profiles_list[:8]:\n",
    "  #     print(profile)\n",
    "else:\n",
    "  print(f\"DEBUG MODE: Using hardcoded emails list with {len(profiles_list)} emails.\")\n",
    "\n",
    "\n",
    "event_upserts = []\n",
    "for index, profile in enumerate(profiles_list):\n",
    "    if index >= EVENTS_MAX:\n",
    "        print(f\"Reached maximum of {EVENTS_MAX} events for this run. Run again to process more.\")\n",
    "        break\n",
    "    if DEBUG_MODE:\n",
    "      print(f\"Creating 'VRChat Edition Code Assigned' event for profile {index+1} of {len(profiles_list)} ({profile['email']}, code {profile['code']})\")  # debug\n",
    "    else:\n",
    "      # set event_triggered_timestamp to the current timestamp for this email in the database\n",
    "      c.execute(\"UPDATE codes SET event_triggered_timestamp = ? WHERE assigned_to IS ? AND event_triggered_timestamp IS NULL\", (datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"), profile['email']))\n",
    "      conn.commit()\n",
    "\n",
    "    event_upserts.append({\n",
    "      \"type\": \"event-bulk-create\",\n",
    "      \"attributes\": {\n",
    "        \"profile\": {\n",
    "          \"data\": {\n",
    "            \"type\": \"profile\",\n",
    "            \"attributes\": {\n",
    "              \"email\": profile['email']\n",
    "            }\n",
    "          }\n",
    "        },\n",
    "        \"events\": {\n",
    "          \"data\": [\n",
    "            {\n",
    "              \"type\": \"event\",\n",
    "              \"attributes\": {\n",
    "                \"properties\": {\n",
    "                  \"vrceCodeAssigned\": profile['code']\n",
    "                },\n",
    "                \"metric\": {\n",
    "                  \"data\": {\n",
    "                    \"type\": \"metric\",\n",
    "                    \"attributes\": {\n",
    "                      \"name\": EVENT_NAME\n",
    "                    }\n",
    "                  }\n",
    "                }\n",
    "              }\n",
    "            }\n",
    "          ]\n",
    "        }\n",
    "      }\n",
    "    })\n",
    "    if len(event_upserts) % 100 == 0:\n",
    "        print(f\"Prepared {len(event_upserts)} events so far. Processing...\")\n",
    "\n",
    "\n",
    "bulk_events_body = {\n",
    "    'data': {\n",
    "        'type': 'event-bulk-create-job',\n",
    "        'attributes': {\n",
    "          'events-bulk-create': {\n",
    "            'data': event_upserts\n",
    "          }\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "\n",
    "print(f\"Arranging bulk \\\"{EVENT_NAME}\\\" event creation for {len(event_upserts)} profiles...\")\n",
    "response = klaviyo.Events.bulk_create_events(bulk_events_body)\n",
    "print(f\"Done. Response:\")\n",
    "pprint.pprint(response, indent=2)\n",
    "conn.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Example bulk_create_events_for_segment() usage\n",
    "vrce_buyers_need_code_seg = 'X8CWen'\n",
    "segment_id = vrce_buyers_need_code_seg\n",
    "event_name = 'TEST EVENT'\n",
    "event_properties = {\n",
    "    \"exampleProperty\": \"exampleValue\"\n",
    "}\n",
    "bulk_create_events_for_segment(segment_id, event_name, event_properties)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
