Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion MixpanelReactNative.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ Pod::Spec.new do |s|
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }

s.dependency "React-Core"
s.dependency "Mixpanel-swift", '6.5.0'
# Local mixpanel-swift with autocapture support
s.dependency "Mixpanel-swift", '~> 6.5'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is local but we could miss this considering the actual release is 6.5.0 and the local testing is 6.5. Lets be careful with making sure we change to correct value.

end
24 changes: 23 additions & 1 deletion Samples/MixpanelStarter/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {OnboardingScreen} from './screens/OnboardingScreen';
import {HomeScreen} from './screens/HomeScreen';
import {FeatureFlagsScreen} from './screens/FeatureFlagsScreen';
import {SettingsScreen} from './screens/SettingsScreen';
import {AutocaptureTestScreen} from './screens/AutocaptureTestScreen';
import {WalkUpTestScreen} from './screens/WalkUpTestScreen';
import {MIXPANEL_TOKEN} from '@env';

const Tab = createBottomTabNavigator();
Expand Down Expand Up @@ -112,6 +114,26 @@ function AppNavigator(): React.JSX.Element {
),
}}
/>
<Tab.Screen
name="Autocapture"
component={AutocaptureTestScreen}
options={{
tabBarLabel: 'Autocapture',
tabBarIcon: ({color}) => (
<Text style={{fontSize: 20, color}}>tap</Text>
),
}}
/>
<Tab.Screen
name="WalkUp"
component={WalkUpTestScreen}
options={{
tabBarLabel: 'Walk-Up',
tabBarIcon: ({color}) => (
<Text style={{fontSize: 20, color}}>🔍</Text>
),
}}
/>
<Tab.Screen
name="Settings"
component={SettingsScreen}
Expand All @@ -130,7 +152,7 @@ function AppNavigator(): React.JSX.Element {
function App(): React.JSX.Element {
return (
<ErrorBoundary>
<MixpanelProvider token={token} trackAutomaticEvents={true} useNative={true} serverURL="https://api-eu.mixpanel.com">
<MixpanelProvider token={token} trackAutomaticEvents={true} useNative={true} serverURL="https://api.mixpanel.com">
<AppNavigator />
</MixpanelProvider>
</ErrorBoundary>
Expand Down
226 changes: 226 additions & 0 deletions Samples/MixpanelStarter/src/screens/WalkUpTestScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import React from 'react';
import {
ScrollView,
View,
Text,
Pressable,
TouchableOpacity,
StyleSheet,
} from 'react-native';

/**
* Walk-Up-to-Clickable-Parent Test Screen
*
* Validates that when a non-interactive leaf view (Text, Image) is tapped,
* the native SDK walks up to the nearest clickable ancestor (Pressable,
* TouchableOpacity) for $el_id resolution.
*
* Run on both iOS and Android. Inspect Mixpanel event stream to verify.
*/
export function WalkUpTestScreen() {
return (
<ScrollView contentContainerStyle={styles.container}>
<Text style={styles.title}>Walk-Up Test Screen</Text>
<Text style={styles.subtitle}>
Tests that tapping a leaf view (Text/Image) inside a clickable wrapper
reports the wrapper's identity as $el_id, not the leaf's hash.
</Text>

{/* 1. Basic Walk-Up */}
<SectionHeader title="Basic Walk-Up" />
<Text style={styles.description}>
Tap the text. $el_id should be "add_to_cart" from the Pressable.
</Text>
<Pressable
style={styles.btn}
onPress={() => {}}
accessible={true}
accessibilityLabel="add_to_cart">
<Text style={styles.btnText}>Add to Cart</Text>
</Pressable>

{/* 2. Nested Pressables */}
<SectionHeader title="Nested Pressables" />
<Text style={styles.description}>
Tap "Delete". Walk-up stops at inner Pressable ("delete_item"), not
outer card ("product_card").
</Text>
<Pressable
style={styles.card}
onPress={() => {}}
accessible={true}
accessibilityLabel="product_card">
<Text style={styles.cardTitle}>Product Name</Text>
<Pressable
style={styles.deleteBtn}
onPress={() => {}}
accessible={true}
accessibilityLabel="delete_item">
<Text style={styles.deleteBtnText}>Delete</Text>
</Pressable>
</Pressable>

{/* 3. Pressable with Image + Text */}
<SectionHeader title="Clickable Container with Icon + Text" />
<Text style={styles.description}>
Tap the icon or text. $el_id should be "checkout_action".
</Text>
<Pressable
style={styles.row}
onPress={() => {}}
accessible={true}
accessibilityLabel="checkout_action">
<Text style={styles.icon}>🛒</Text>
<Text style={styles.rowText}>Proceed to Checkout</Text>
</Pressable>

{/* 4. Non-interactive text */}
<SectionHeader title="No Clickable Ancestor" />
<Text style={styles.description}>
Tap below. No Pressable ancestor exists. $el_id = hash fallback.
</Text>
<View style={styles.plainTextContainer}>
<Text style={styles.plainText}>Terms and Conditions apply.</Text>
</View>

{/* 5. Leaf with own identity */}
<SectionHeader title="Leaf Has Own Identity" />
<Text style={styles.description}>
Tap the text. Even though it has its own accessibilityLabel
("inner_label"), walk-up still activates and takes the clickable
parent's identity. $el_id = "outer_button".
</Text>
<Pressable
style={styles.btn}
onPress={() => {}}
accessible={true}
accessibilityLabel="outer_button">
<Text
style={styles.btnText}
accessible={true}
accessibilityLabel="inner_label">
I have my own identity
</Text>
</Pressable>

{/* 6. View flattening */}
<SectionHeader title="View Flattening" />
<Text style={styles.description}>
Intermediate View has no visual props and will be flattened away. Tap the
text — walk-up should still find "flattened_pressable".
</Text>
<Pressable
style={styles.btn}
onPress={() => {}}
accessible={true}
accessibilityLabel="flattened_pressable">
<View>
<Text style={styles.btnText}>Text inside flattened View</Text>
</View>
</Pressable>

{/* 7. TouchableOpacity variant */}
<SectionHeader title="TouchableOpacity Variant" />
<Text style={styles.description}>
Same as basic walk-up but with TouchableOpacity. $el_id should be
"touchable_btn".
</Text>
<TouchableOpacity
style={styles.btn}
onPress={() => {}}
accessible={true}
accessibilityLabel="touchable_btn">
<Text style={styles.btnText}>TouchableOpacity Button</Text>
</TouchableOpacity>
</ScrollView>
);
}

function SectionHeader({title}: {title: string}) {
return <Text style={styles.sectionHeader}>{title}</Text>;
}

const styles = StyleSheet.create({
container: {
padding: 16,
paddingBottom: 48,
},
title: {
fontSize: 22,
fontWeight: 'bold',
marginBottom: 4,
},
subtitle: {
fontSize: 13,
color: '#666',
marginBottom: 16,
},
sectionHeader: {
fontSize: 17,
fontWeight: '700',
marginTop: 20,
marginBottom: 4,
color: '#333',
},
description: {
fontSize: 12,
color: '#888',
marginBottom: 6,
},
btn: {
backgroundColor: '#2196F3',
padding: 14,
borderRadius: 8,
alignItems: 'center',
marginBottom: 8,
},
btnText: {
color: '#fff',
fontSize: 15,
fontWeight: '600',
},
card: {
backgroundColor: '#f5f5f5',
borderRadius: 12,
padding: 16,
marginBottom: 8,
},
cardTitle: {
fontSize: 16,
fontWeight: 'bold',
marginBottom: 8,
},
deleteBtn: {
backgroundColor: '#f44336',
padding: 10,
borderRadius: 8,
alignItems: 'center',
},
deleteBtnText: {
color: '#fff',
fontWeight: '600',
},
row: {
flexDirection: 'row',
alignItems: 'center',
padding: 16,
backgroundColor: '#f5f5f5',
borderRadius: 8,
marginBottom: 8,
},
icon: {
fontSize: 20,
marginRight: 12,
},
rowText: {
fontSize: 16,
},
plainTextContainer: {
padding: 8,
marginBottom: 8,
},
plainText: {
fontSize: 14,
color: '#888',
},
});
4 changes: 3 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ android {
}

repositories {
mavenLocal() // Local builds of mixpanel-android with autocapture support
mavenCentral()
maven {
url 'https://maven.google.com/'
Expand All @@ -41,5 +42,6 @@ repositories {

dependencies {
implementation 'com.facebook.react:react-native:+'
implementation 'com.mixpanel.android:mixpanel-android:8.9.0'
// Local mixpanel-android with autocapture support (publish locally with: ./gradlew :analytics:publishToMavenLocal -x signReleasePublication)
implementation 'com.mixpanel.android:mixpanel-android:9.0.0-beta'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Android dependency is locally scoped

When a consumer or clean CI environment builds this package without first publishing mixpanel-android:9.0.0-beta to Maven Local, Gradle cannot resolve the new implementation dependency, causing the Android application build to fail.

}
Loading
Loading