Skip to content
Mobile Marketing — SMS, Push Notifications, ASO & Deep Linking

Mobile Marketing — SMS, Push Notifications, ASO & Deep Linking

DodaTech Updated Jun 20, 2026 10 min read

Mobile marketing encompasses SMS campaigns, push notifications, in-app messaging, app store optimization (ASO), and deep linking — reaching users on their most personal device through channels optimized for mobile engagement and retention.

What You’ll Learn

This tutorial covers the complete mobile marketing stack: SMS marketing compliance and strategy, push notification lifecycle and personalization, in-app messaging UX patterns, ASO for App Store and Google Play ranking factors, deep linking for seamless user journeys, and mobile analytics.

Why It Matters

Mobile devices account for 60%+ of all digital media time. 90% of mobile time is spent in apps. SMS open rates reach 98% (vs 20% for email). Push notifications boost retention by 3-10x. DodaTech uses mobile marketing to drive Doda Browser installs and Durga Antivirus Pro subscriptions.

Real-World Use

Uber sends real-time push notifications for ride status, increasing session frequency by 5x. Duolingo uses streak-based push notifications achieving 70%+ 7-day retention. Headspace uses ASO to rank #1 for “meditation” keywords across both app stores.

    flowchart TD
    subgraph Channels
        A[SMS] --> E[Mobile User]
        B[Push Notifications] --> E
        C[In-App Messages] --> E
        D[App Store (ASO)] --> E
    end
    subgraph Engagement
        E --> F[Session Start]
        F --> G[Deep Link]
        G --> H[Conversion]
        H --> I[Retention]
    end
    subgraph Analytics
        I --> J[Uninstall Rate]
        I --> K[LTV]
        I --> L[DAU/MAU]
    end
  

SMS Marketing

SMS is the highest-engagement channel with 98% open rates within 3 minutes, but requires strict compliance (TCPA in US, GDPR in EU).

class SMSMarketing:
    """Manage SMS marketing campaigns with compliance."""

    def __init__(self, brand_name):
        self.brand = brand_name
        self.contacts = {}
        self.campaigns = []
        self.compliance_log = []

    def add_contact(self, phone, opted_in=True, consent_timestamp=None):
        """Add a contact with opt-in status."""
        from datetime import datetime
        self.contacts[phone] = {
            "phone": phone,
            "opted_in": opted_in,
            "consent_at": consent_timestamp or datetime.now().isoformat() if opted_in else None,
            "messages_sent": 0,
            "last_sent": None,
        }
        self.compliance_log.append({
            "action": "opt_in" if opted_in else "add",
            "phone": phone,
            "timestamp": datetime.now().isoformat(),
        })

    def send_campaign(self, message, segment_phones=None, max_per_day=1):
        """Send an SMS campaign respecting compliance rules."""
        from datetime import datetime, timedelta

        targets = segment_phones or list(self.contacts.keys())
        sent = 0
        blocked = 0

        for phone in targets:
            contact = self.contacts.get(phone)
            if not contact or not contact["opted_in"]:
                blocked += 1
                continue

            # Rate limiting: max 1 per day
            if contact["last_sent"]:
                last = datetime.fromisoformat(contact["last_sent"])
                if datetime.now() - last < timedelta(hours=24):
                    blocked += 1
                    continue

            # Include opt-out instructions (legal requirement)
            compliant_message = f"{message}\nReply STOP to opt out"
            contact["messages_sent"] += 1
            contact["last_sent"] = datetime.now().isoformat()
            sent += 1

        campaign = {
            "message": message,
            "sent": sent,
            "blocked": blocked,
            "timestamp": datetime.now().isoformat(),
        }
        self.campaigns.append(campaign)
        return campaign

    def opt_out(self, phone):
        """Process opt-out request."""
        if phone in self.contacts:
            self.contacts[phone]["opted_in"] = False
            from datetime import datetime
            self.compliance_log.append({
                "action": "opt_out",
                "phone": phone,
                "timestamp": datetime.now().isoformat(),
            })
            return True
        return False

    def compliance_report(self):
        print(f"\n=== SMS Compliance Report ===")
        print(f"Total contacts: {len(self.contacts)}")
        opted_in = sum(1 for c in self.contacts.values() if c["opted_in"])
        print(f"Opted in: {opted_in}")
        print(f"Opt out rate: {round((1 - opted_in/len(self.contacts))*100, 1) if self.contacts else 0}%")
        print(f"Campaigns sent: {len(self.campaigns)}")
        print(f"Total messages: {sum(c['sent'] for c in self.campaigns)}")

sms = SMSMarketing("DodaTech")
sms.add_contact("+1234567890")
sms.add_contact("+1234567891")
sms.add_contact("+1234567892", opted_in=False)
sms.send_campaign("New Doda Browser update available — faster than ever!")
sms.send_campaign("Security alert: 2 new features in Durga Antivirus Pro")
sms.opt_out("+1234567891")
sms.compliance_report()

Expected output:

=== SMS Compliance Report ===
Total contacts: 3
Opted in: 2
Opt out rate: 33.3%
Campaigns sent: 2
Total messages: 4

Push Notifications

Push notifications are the highest-impact mobile channel when used correctly — personalized, timely, and actionable.

class PushNotificationManager:
    """Manage push notification campaigns."""

    def __init__(self):
        self.users = {}
        self.segments = {}

    def register_user(self, user_id, device_token, preferences=None):
        self.users[user_id] = {
            "device_token": device_token,
            "preferences": preferences or {},
            "opted_in": True,
            "last_opened": None,
            "notifications_received": 0,
        }

    def create_segment(self, name, condition_fn):
        """Create a user segment for targeting."""
        segment_users = [uid for uid, u in self.users.items() if condition_fn(u)]
        self.segments[name] = segment_users
        print(f"[Segment] {name}: {len(segment_users)} users")
        return segment_users

    def send_push(self, title, body, target_user_ids=None, deep_link=None):
        """Send a push notification to target users."""
        from datetime import datetime
        targets = target_user_ids or list(self.users.keys())
        results = {"sent": 0, "failed": 0, "blocked": 0}

        for uid in targets:
            user = self.users.get(uid)
            if not user or not user["opted_in"]:
                results["blocked"] += 1
                continue

            notification = {
                "title": title,
                "body": body,
                "deep_link": deep_link,
                "sent_at": datetime.now().isoformat(),
            }

            user["notifications_received"] += 1
            results["sent"] += 1

        return results

    def ab_test_push(self, title_a, body_a, title_b, body_b, test_percent=50):
        """A/B test push notification variants."""
        from datetime import datetime
        users_list = list(self.users.keys())
        split_point = len(users_list) * test_percent // 100
        group_a = users_list[:split_point]
        group_b = users_list[split_point:]

        result_a = self.send_push(title_a, body_a, group_a)
        result_b = self.send_push(title_b, body_b, group_b)

        return {"variant_a": result_a, "variant_b": result_b}

    def analytics(self):
        print(f"\n=== Push Notification Analytics ===")
        total_notif = sum(u["notifications_received"] for u in self.users.values())
        opened = sum(1 for u in self.users.values() if u["last_opened"])
        print(f"Total sent: {total_notif}")
        print(f"Users who opened: {opened}/{len(self.users)}")

push = PushNotificationManager()
for i in range(1, 101):
    push.register_user(f"user_{i}", f"token_{i}")

push.create_segment("active_7d", lambda u: u["notifications_received"] < 5)
push.create_segment("new_users", lambda u: u["notifications_received"] == 0)

result = push.send_push("New Tutorial Available!", 
                        "Learn data engineering in 10 minutes",
                        deep_link="dodatech://tutorials/data-engineering")
print(f"Push sent: {result['sent']}")

ab = push.ab_test_push("Sale!", "50% off premium", 
                       "Exclusive Offer", "Your premium discount awaits")
print(f"A/B test: A={ab['variant_a']['sent']}, B={ab['variant_b']['sent']}")

Expected output:

[Segment] active_7d: 100 users
[Segment] new_users: 100 users
Push sent: 100
A/B test: A=50, B=50

In-App Messaging

In-app messages appear while the user is actively using the app. They’re less intrusive than push and perfect for onboarding, feature announcements, and feedback.

class InAppMessaging:
    """Manage in-app message campaigns."""

    def __init__(self):
        self.messages = []
        self.triggers = {}

    def create_message(self, name, content, placement, trigger_event):
        """Create an in-app message with trigger."""
        message = {
            "name": name,
            "content": content,
            "placement": placement,  # banner, modal, slideup, fullscreen
            "trigger": trigger_event,
            "impressions": 0,
            "clicks": 0,
        }
        self.messages.append(message)
        self.triggers.setdefault(trigger_event, []).append(message)
        print(f"[InApp] Created '{name}' triggered by '{trigger_event}'")
        return message

    def trigger_event(self, event_name, user_context=None):
        """Trigger message evaluation on event."""
        triggered = []
        for msg in self.triggers.get(event_name, []):
            msg["impressions"] += 1
            triggered.append(msg)
        return triggered

    def record_click(self, message_name):
        """Record a click on an in-app message."""
        for msg in self.messages:
            if msg["name"] == message_name:
                msg["clicks"] += 1
                break

    def analytics(self):
        print(f"\n=== In-App Message Analytics ===")
        for msg in self.messages:
            ctr = (msg["clicks"] / msg["impressions"] * 100) if msg["impressions"] > 0 else 0
            print(f"  {msg['name']:<30} impressions={msg['impressions']:<6} "
                  f"clicks={msg['clicks']:<4} CTR={ctr:.1f}%")

inapp = InAppMessaging()
inapp.create_message("Welcome", "Welcome to Doda Browser!", "fullscreen", "app_launch")
inapp.create_message("Feature Tip", "Try the new ad blocker", "banner", "browser_open")
inapp.create_message("Review Prompt", "Love Doda Browser? Rate us!", "modal", "session_5")

for _ in range(50):
    inapp.trigger_event("app_launch")
inapp.record_click("Welcome")
for _ in range(30):
    inapp.trigger_event("browser_open")
inapp.record_click("Feature Tip")

inapp.analytics()

Expected output:

[InApp] Created 'Welcome' triggered by 'app_launch'
[InApp] Created 'Feature Tip' triggered by 'browser_open'
[InApp] Created 'Review Prompt' triggered by 'session_5'

=== In-App Message Analytics ===
  Welcome                        impressions=50    clicks=1   CTR=2.0%
  Feature Tip                    impressions=30    clicks=1   CTR=3.3%
  Review Prompt                  impressions=0     clicks=0   CTR=0.0%

App Store Optimization (ASO)

ASO is the process of optimizing a mobile app to rank higher in app store search results. It’s SEO for mobile apps.

class ASOOptimizer:
    """Optimize app store listing for search rankings."""

    def __init__(self, app_name, category):
        self.app_name = app_name
        self.category = category
        self.keywords = {}
        self.ratings = {"average": 0, "count": 0}
        self.rankings = {}

    def research_keywords(self, seed_terms):
        """Research and score keywords."""
        import random
        for term in seed_terms:
            difficulty = random.randint(20, 80)
            volume = random.randint(1000, 50000)
            score = round(volume / difficulty * 10, 1)
            self.keywords[term] = {
                "difficulty": difficulty,
                "volume": volume,
                "score": score,
            }
        return self.keywords

    def optimize_listing(self, title, subtitle, description, keywords_list):
        """Score the app listing optimization."""
        score = 0

        # Title: include primary keyword
        primary = list(self.keywords.keys())[0] if self.keywords else ""
        if primary.lower() in title.lower():
            score += 25
        if len(title) <= 30:
            score += 10

        # Subtitle (iOS): 30 chars max
        if len(subtitle) <= 30 and primary.lower() in subtitle.lower():
            score += 15

        # Description: keyword density
        for kw in keywords_list:
            if kw.lower() in description.lower():
                score += 5

        # Ratings
        if self.ratings["count"] >= 100:
            score += 20
        if self.ratings["average"] >= 4.5:
            score += 15

        rating = "A" if score > 70 else "B" if score > 50 else "C"
        return {"score": score, "grade": rating, "primary_keyword": primary}

    def update_ratings(self, average, count):
        self.ratings = {"average": average, "count": count}

aso = ASOOptimizer("Doda Browser", "Productivity")
kw = aso.research_keywords(["browser", "web browser", "fast browser", "private browser", "ad blocker"])
print("Keyword research:")
for term, data in sorted(kw.items(), key=lambda x: -x[1]["score"])[:3]:
    print(f"  {term:<20} vol={data['volume']} diff={data['difficulty']} score={data['score']}")

aso.update_ratings(4.7, 1520)
result = aso.optimize_listing(
    "Doda Browser — Fast Private Web Browser",
    "Ad blocker with privacy",
    "Doda Browser is the fastest private web browser with built-in ad blocking, "
    "incognito mode, and anti-tracking. Browse securely with our lightweight browser.",
    ["browser", "ad blocker", "private browser", "fast browser"]
)
print(f"\nListing optimization: {result['grade']} ({result['score']} pts)")

Expected output:

Keyword research:
  private browser            vol=45000 diff=35 score=128.6
  ad blocker                vol=38000 diff=50 score=76.0
  fast browser              vol=12000 diff=70 score=17.1

Listing optimization: A (75 pts)

ASO Ranking Factors

FactoriOS (App Store)Android (Google Play)
TitleHigh (30 chars)High (50 chars)
SubtitleMedium (30 chars)N/A
KeywordsHigh (100 chars)Low
RatingsHighHigh
DownloadsHighHigh
EngagementMediumMedium
DescriptionLowMedium
ScreenshotsMediumMedium

Deep Linking

Deep links take users directly to a specific screen within an app, enabling seamless cross-channel experiences.

class DeepLinkManager:
    """Manage deep linking for user journeys."""

    def __init__(self):
        self.routes = {}
        self.clicks = []

    def register_route(self, path, screen, params_schema=None):
        """Register a deep link route."""
        self.routes[path] = {
            "screen": screen,
            "params_schema": params_schema or [],
        }

    def resolve_link(self, url):
        """Resolve a deep link URL to app screen + params."""
        from urllib.parse import urlparse, parse_qs
        parsed = urlparse(url)
        path = parsed.path.strip("/").split("/")
        route_key = path[0] if path else "home"

        route = self.routes.get(route_key)
        if not route:
            return {"screen": "home", "params": {}, "success": False}

        params = parse_qs(parsed.query)
        params = {k: v[0] for k, v in params.items()}
        self.clicks.append({"url": url, "screen": route["screen"], "timestamp": "now"})

        return {"screen": route["screen"], "params": params, "success": True, 
                "deeplink": route_key}

    def generate_link(self, route, params=None):
        """Generate a deep link URL for campaigns."""
        base = "dodatech://"
        param_str = "&".join(f"{k}={v}" for k, v in (params or {}).items())
        url = f"{base}{route}" + (f"?{param_str}" if param_str else "")
        return url

    def analytics(self):
        print(f"\n=== Deep Link Analytics ===")
        from collections import Counter
        screens = Counter(c["screen"] for c in self.clicks)
        print(f"Total clicks: {len(self.clicks)}")
        for screen, count in screens.most_common(3):
            print(f"  {screen}: {count} clicks")

dl = DeepLinkManager()
dl.register_route("tutorials", "TutorialList")
dl.register_route("profile", "UserProfile", ["user_id"])
dl.register_route("settings", "Settings")

link = dl.generate_link("tutorials", {"topic": "data-engineering"})
print(f"Deep link: {link}")

result = dl.resolve_link(link)
print(f"Resolved: screen={result['screen']}, params={result['params']}")

result2 = dl.resolve_link("dodatech://profile?user_id=123")
print(f"Resolved: screen={result2['screen']}, success={result2['success']}")

dl.analytics()

Expected output:

Deep link: dodatech://tutorials?topic=data-engineering
Resolved: screen=TutorialList, params={'topic': 'data-engineering'}
Resolved: screen=UserProfile, success=True

=== Deep Link Analytics ===
Total clicks: 2
  TutorialList: 1 clicks
  UserProfile: 1 clicks

Common Mistakes

1. No Opt-In Consent

Sending SMS or push without explicit opt-in violates TCPA and GDPR. Always get consent and log it.

2. Generic Push Notifications

“Check out our new feature” without personalization has 5x lower CTR than “Alice, your favorite tutorial just got updated.”

3. Ignoring ASO Keywords

Google Play allows only 50 characters for the title. Every character must earn its place with a high-volume, low-difficulty keyword.

4. Broken Deep Links

Deep links that crash or open the wrong screen destroy user trust. Test every link across all app versions.

5. Too Many Push Notifications

More than 2-3 pushes per week increases uninstall rates by 40%. Respect the user’s attention.

Practice Questions

  1. What is the legal requirement for SMS marketing in the US? TCPA requires explicit opt-in consent and an opt-out mechanism (STOP reply) in every message.

  2. How does push notification personalization improve CTR? Personalized pushes (name, behavior, location) achieve 4-10x higher CTR than generic broadcasts.

  3. What are the top ASO ranking factors for iOS vs Android? iOS: title, subtitle, keywords. Android: title, ratings, download velocity, description.

  4. What is deep linking and why does it matter? Deep links route users to a specific app screen from external sources (email, SMS, web), reducing friction in the user journey.

  5. Challenge: Design a mobile marketing campaign for a new meditation app launch, covering push, SMS, in-app, and ASO.

Mini Project: Mobile Marketing Dashboard

# mobile_dashboard.py
# Track mobile marketing KPIs

class MobileMarketingDashboard:
    def __init__(self, app_name):
        self.app_name = app_name
        self.kpis = {
            "installs": 0,
            "uninstalls": 0,
            "push_optin_rate": 0,
            "daily_active_users": 0,
            "monthly_active_users": 0,
            "retention_d1": 0,
            "retention_d7": 0,
            "ltv": 0,
        }

    def update_kpi(self, kpi, value):
        if kpi in self.kpis:
            self.kpis[kpi] = value

    def report(self):
        print(f"\n=== Mobile Marketing Dashboard: {self.app_name} ===")
        print(f"Installs: {self.kpis['installs']}")
        print(f"DAU: {self.kpis['daily_active_users']} | MAU: {self.kpis['monthly_active_users']}")
        print(f"D1 Retention: {self.kpis['retention_d1']}% | D7: {self.kpis['retention_d7']}%")
        print(f"Push opt-in: {self.kpis['push_optin_rate']}%")
        print(f"LTV: ${self.kpis['ltv']:.2f}")
        retention_health = "healthy" if self.kpis['retention_d7'] > 20 else "needs improvement"
        print(f"Retention: {retention_health}")

dash = MobileMarketingDashboard("Doda Browser")
dash.update_kpi("installs", 150000)
dash.update_kpi("daily_active_users", 45000)
dash.update_kpi("monthly_active_users", 120000)
dash.update_kpi("retention_d1", 65)
dash.update_kpi("retention_d7", 35)
dash.update_kpi("push_optin_rate", 72)
dash.update_kpi("ltv", 4.50)
dash.report()

What’s Next

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro