Overview
This article covers implementing Google Tag Manager (GTM), Google Analytics 4 (GA4), Meta Pixel, LinkedIn Insight Tag, and other tracking tools. It is intended to be the source of truth for customers, analytics consultants, and developers who are configuring attribution and event tracking for Teachable schools.
NOTE: We recommend leveraging a direct integration wherever possible as opposed to the code snippet to simplify setup and possible tracking complexities.
Summary & Best Practices
Use native integrations wherever possible for broader support and easy-of-setup.
Avoid duplicating container IDs β use only the integration without combining it with a code snippet
Avoid using both the Google Analytics and Google Tag Manager integrations, as you may receive duplicate events
Checkout pages do not allow custom code snippets β use the integrations to track sales attribution.
add_to_cart and purchase events are available in the data layer.
For advanced tracking, use GTM's built-in features and preview/debug mode to validate data layer pushes
Code Snippets vs. Integrations
Teachable supports tracking tools via two mechanisms:
Code Snippets: Manually added through the "Code Snippets" settings in the admin.
Native Integrations: Enabled via the "App Hub" section in the admin dashboard (e.g., GTM, GA4, Meta Pixel, etc.).
Type | How It's Added | Where It Loads |
Code Snippet | Manually in Admin > Code Snippets | Most student-facing pages |
Integration | Admin > Integrations | Broadly across all pages, including Checkout |
Important: Due to security concerns, there are pages where the integration is present but the code snippet is not.
Page-Level Presence of Integrations and Snippets
0 = Neither present
1 = Integration only present
2 = Code Snippet + Integration Present
Page | GA4 | GTM | Meta Pixel | TikTok | Segment | ||
Landing Page (/) | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
Sales Page (/p) | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
Checkout (/checkout) | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
Thank You Page | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
Product Detail (/l) | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
Course Index (/courses) | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
Course Curriculum (/courses/enrolled/*) | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
Lecture Player(/lectures) | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
Student Profile, Address, Purchase History, Contact | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
Coaching Enrolled | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
Coaching Milestones | 1 | 1 | 1 | 1 | 0 | 0 | 0 |
Login / Signup / OTP | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Data Layer Events for Checkout & Purchase
Teachable fires 2 key data layer events to track checkout conversion:
add_to_cart: Fired when a user lands on the checkout
purchase: Fired after a customer completes a purchase
We follow the recommended data structure for each analytics integration, with the format detailed below.
Google Analytics 4 (GA4)
Google Analytics 4 (GA4)
Add to Cart Event
{
send_to: string, // GA4 tag ID
transaction_id: string, // Order token
currency: string, // e.g., 'USD'
value: number, // e.g., 1.00
coupon: string, // e.g., 'DISCOUNT10'
tax: string, // e.g., '0.08'
items: [
{
item_id: string, // e.g., 'course_123'
item_name: string, // e.g., 'Advanced JavaScript'
price: string, // e.g., '1.00'
quantity: number, // e.g., 1
product_type: string, // e.g., 'Course'
}
]
}
Purchase Event
{
send_to: string, // GA4 tag ID
value: number, // e.g., 1.00
currency: string, // e.g., 'USD'
tax: string, // e.g., '0.08'
coupon: string, // e.g., 'DISCOUNT10'
transaction_id: string, // Order token
items: [
{
item_id: string, // e.g., 'course_123'
item_name: string, // e.g., 'Advanced JavaScript'
price: string, // e.g., '1.00'
quantity: number, // e.g., 1
product_type: string, // e.g., 'Course'
}
]
}
Google Tag Manager (GTM)
Google Tag Manager (GTM)
Add to Cart Event
{
event: 'add_to_cart',
ecommerce: {
currency: string, // e.g., 'USD'
value: string, // e.g., '1.00'
coupon: string, // e.g., 'DISCOUNT10'
tax: string, // e.g., '0.08'
items: [
{
item_id: string, // e.g., 'course_123'
item_name: string, // e.g., 'Advanced JavaScript'
price: string, // e.g., '1.00'
quantity: number, // e.g., 1
product_type: string, // e.g., 'Course'
}
]
}
}
Purchase Event
{
event: 'purchase',
ecommerce: {
currency: string, // e.g., 'USD'
value: number, // e.g., 1.00
coupon: string, // e.g., 'DISCOUNT10'
tax: string, // e.g., '0.08'
transaction_id: string, // Order token
items: [
{
item_id: string, // e.g., 'course_123'
item_name: string, // e.g., 'Advanced JavaScript'
price: string, // e.g., '1.00'
quantity: number, // e.g., 1
product_type: string, // e.g., 'Course'
}
]
}
}
Meta Pixel (Facebook)
Meta Pixel (Facebook)
βAddToCart Event
{
content_ids: string[], // Array of item IDs
content_type: string, // 'product'
currency: string, // e.g., 'USD'
value: number, // e.g., 1.00
coupon: string, // e.g., 'DISCOUNT10'
contents: [
{
id: string, // e.g., 'course_123'
quantity: number, // e.g., 1
content_category: string // e.g., 'Course'
}
]
}
Purchase Event
{
content_ids: string[], // Array of item IDs
content_type: string, // 'product'
currency: string, // e.g., 'USD'
num_items: number, // Total items count
value: number, // e.g., 1.00
event_id: string, // Order token (Any string or hashed ID that can identify a unique event)
order_id: string, // Order token
contents: [
{
id: string, // e.g., 'course_123'
quantity: number, // e.g., 1
content_category: string // e.g., 'Course'
}
]
}
Pinterest Tag
Pinterest Tag
AddToCart Event
{
value: number, // e.g., 1.00
order_quantity: number, // Total items count
currency: string, // e.g., 'USD'
promo_code: string, // e.g., 'DISCOUNT10'
order_id: string, // Order token
line_items: [
{
product_name: string, // e.g., 'Advanced JavaScript'
product_id: string, // e.g., 'course_123'
product_price: string, // e.g., '1.00'
product_quantity: number, // e.g., 1
product_category: string // e.g., 'Course'
}
]
}
Purchase Event
{
value: number, // e.g., 1.00
order_quantity: number, // Total items count
currency: string, // e.g., 'USD'
promo_code: string, // e.g., 'DISCOUNT10'
order_id: string, // Order token
line_items: [
{
product_name: string, // e.g., 'Advanced JavaScript'
product_id: string, // e.g., 'course_123'
product_price: string, // e.g., '1.00'
product_quantity: number, // e.g., 1
product_category: string // e.g., 'Course'
}
]
}
TikTok Pixel
TikTok Pixel
AddToCart Event
{
content_type: string, // 'product'
value: string, // e.g., '1.00'
quantity: number, // Total items count
currency: string, // e.g., 'USD'
content_ids: string[], // Array of item IDs
coupon: string, // e.g., 'DISCOUNT10'
contents: [
{
id: string, // e.g., 'course_123'
quantity: number, // e.g., 1
content_category: string // e.g., 'Course'
}
]
}
Purchase Event
{
event_id: string, // Order token (Any string or hashed ID that can identify a unique event)
content_type: string, // 'product'
value: number, // e.g., 1.00
currency: string, // e.g., 'USD'
quantity: number, // Total items count
content_ids: string[], // Array of item IDs
contents: [
{
id: string, // e.g., 'course_123'
quantity: number, // e.g., 1
content_category: string // e.g., 'Course'
}
]
}
Segment
Segment
Product Added Event
{
product_id: string, // Main product ID
name: string, // Main product name
price: string, // e.g., '1.00'
quantity: number, // Total items count
coupon: string, // e.g., 'DISCOUNT10'
position: number, // Always 1
url: string, // Current page URL
products: [
{
product_id: string, // e.g., 'course_123'
name: string, // e.g., 'Advanced JavaScript'
price: number, // e.g., 1.00
quantity: number, // e.g., 1
product_type: string // e.g., 'Course'
}
]
}
Order Completed Event
{
total: number, // e.g., 1.00
revenue: number, // e.g., 1.00
currency: string, // e.g., 'USD'
tax: string, // e.g., '0.08'
coupon: string, // e.g., 'DISCOUNT10'
order_id: string, // Order token
products: [
{
product_id: string, // e.g., 'course_123'
name: string, // e.g., 'Advanced JavaScript'
price: number, // e.g., 1.00
quantity: number, // e.g., 1
product_type: string // e.g., 'Course'
}
]
}
GTM Container Duplication Behavior
If both the GTM integration and a manual code snippet are added with the same container ID, GTM will deduplicate automatically:
GTM detects existing containers and prevents loading the same container twice.
However, if different container IDs are added via:
App integration (e.g., GTM container ID in Teachable settings), and
A separate manual snippet in the header
Then two containers will load, which can result in duplicate events or parallel tracking setups.
Recommendation: Use only the GTM integration and avoid also adding the GTM container via code snippets.