Skill: ivangdavila/google-play-store (version 1.0.0)

--- name: Google Play Store slug: google-play-store version: 1.0.0 homepage: https://clawic.com/skills/google-play-store description: Publish, optimize, and scale Android apps on Google Play with release automation, ASO, policy compliance, and rejection recovery. metadata: {"clawdbot":{"emoji":"🤖","requires":{"bins":[]},"os":["linux","darwin","win32"]}} --- ## Setup On first use, read `setup.md` for integration guidelines. ## When to Use User needs to publish, manage, or optimize Android apps on Google Play. Agent handles release workflows, store optimization, policy compliance, review processes, and rejection troubleshooting. ## Architecture Memory lives in `~/google-play-store/`. See `memory-template.md` for structure. ``` ~/google-play-store/ ├── memory.md # Account, apps, preferences ├── apps/ # Per-app tracking │ └── {package}/ # Package-specific notes └── checklists/ # Saved submission checklists ``` ## Quick Reference | Topic | File | |-------|------| | Setup process | `setup.md` | | Memory template | `memory-template.md` | | Release tracks and rollouts | `tracks.md` | | App Store Optimization | `aso.md` | | Policy compliance | `policies.md` | | Rejection recovery | `rejections.md` | | Automation with Fastlane | `fastlane.md` | ## Core Rules ### 1. Release Track Progression | Track | Purpose | Review | Users | |-------|---------|--------|-------| | Internal | Daily builds, QA | None | 100 max | | Closed | Beta testers | 2-6h | Email list | | Open | Public beta | 2-6h | Anyone joins | | Production | Full release | 2-24h | Everyone | **Mandatory progression for new apps:** ``` Internal → Closed (20+ testers, 14+ days) → Production ``` Skip this = instant rejection. Start closed testing on day one. ### 2. Pre-Submission Checklist Run before EVERY submission: ``` CONTENT [ ] Privacy policy URL live and HTTPS [ ] Data safety form 100% complete [ ] Content rating questionnaire done [ ] All screenshots show real app (no placeholders) [ ] Feature graphic 1024x500 uploaded TECHNICAL [ ] Target SDK ≥ 34 (Android 14) [ ] versionCode higher than ALL previous uploads [ ] Signed with correct key [ ] No hardcoded API keys in code [ ] ProGuard/R8 not breaking functionality TESTING (new apps only) [ ] 20+ testers opted in (not just invited) [ ] 14+ consecutive days completed [ ] Crash-free rate > 99% ``` ### 3. Version Code Strategy ``` versionCode must ALWAYS increase. Cannot reuse. Ever. Pattern: YYYYMMDDHH Example: 2025022514 (Feb 25, 2025, 2pm) Why: Rejected uploads "burn" the versionCode. Multiple builds per day need unique codes. ``` ### 4. App Signing Models | Model | Control | Recovery | Best For | |-------|---------|----------|----------| | Google-managed | Google holds key | Easy | New apps | | Upload key | You sign, Google re-signs | Medium | Most apps | | Self-managed | Full control | Hard | Enterprise | **Recommendation:** Google-managed for new apps. Upload key for updates. **Critical:** Export and backup your upload key immediately after creating it. ### 5. Staged Rollout Protocol | Stage | % | Duration | Gate | |-------|---|----------|------| | Canary | 1% | 24-48h | Crashes < 0.1% | | Early | 5% | 48-72h | ANRs < 0.5% | | Mid | 20% | 72-96h | Ratings stable | | Late | 50% | 96-120h | No regressions | | Full | 100% | — | All clear | **Halt triggers:** Crash spike, ANR spike, 1-star surge, critical bug reports. ### 6. ASO Essentials | Element | Limit | Impact | |---------|-------|--------| | Title | 30 chars | Highest | | Short description | 80 chars | High | | Full description | 4000 chars | Medium | | Screenshots | 8 per type | High | | Feature graphic | 1024x500 | Medium | **Keyword strategy:** - Title: Primary keyword + brand - Short desc: Top 3 keywords naturally - Full desc: Long-tail throughout - Update quarterly based on Search Console ### 7. Response Time SLAs | Action | Google Response | Your Deadline | |--------|-----------------|---------------| | Policy email | 7 days to fix | Respond in 3 | | Appeal | 3-7 days | Submit in 24h | | Data request | 30 days | Complete in 14 | | Critical issue | 24h suspension | Immediate | **Rule:** Never ignore policy emails. Silence = admission. ## Common Traps ### Publishing Traps - **Skipped closed testing** → Cannot release to production. 20 testers + 14 days mandatory for new apps. - **Data safety incomplete** → Instant rejection. Fill EVERY field even if "no data collected." - **Screenshots with mockups** → Rejection for misleading. Use real app screenshots only. - **Privacy policy 404** → Rejection. Verify URL works before every submission. ### Technical Traps - **versionCode not incremented** → Upload rejected. Even rejected uploads burn codes. - **Target SDK too old** → Rejection. Check current requirement before building. - **Forgot upload key password** → Cannot update app. Store password in password manager. - **ProGuard broke app** → Crashes after release. Always test release build. ### Policy Traps - **Undeclared permissions** → Policy violation. Justify EVERY sensitive permission. - **Background location without need** → Rejection + strike. Remove or justify with video. - **Kids content undeclared** → Policy violation. If ANY appeal to children, declare it. - **Deceptive ads** → Suspension risk. Follow interstitial timing and close button rules. ### Business Traps - **No staged rollout** → Bad update hits everyone. Always start at 1%. - **Ignored policy email** → Escalation to strike. Respond within 3 days. - **Multiple accounts to evade** → Termination. One violation becomes account death. ## Security & Privacy **Data that stays local:** - Package names and app status in ~/google-play-store/ - Submission checklists and workflow notes - Release history and lessons learned **This skill stores ONLY non-sensitive metadata:** - App names and package identifiers - Track status (internal/closed/production) - Workflow preferences (manual vs CI/CD tool names) - Checklist progress **This skill does NOT store and will refuse:** - API keys, service account JSON content - Keystore files or passwords - OAuth tokens or Play Console credentials - Any secret or credential material **This skill does NOT:** - Upload apps or make network requests - Access signing keys or certificates - Execute Fastlane commands directly User manages all credentials in their CI/CD system and runs commands themselves. The Fastlane examples are documentation only. ## Related Skills Install with `clawhub install <slug>` if user confirms: - `android` — Android development - `app-store` — iOS and Android publishing - `mobile` — Cross-platform mobile ## Feedback - If useful: `clawhub star google-play-store` - Stay updated: `clawhub sync`

path: aso.md
content: # App Store Optimization — Google Play Store

## Ranking Factors

| Factor | Weight | Your Control |
|--------|--------|--------------|
| Keyword relevance | High | Full |
| Download velocity | High | Partial |
| Ratings & reviews | High | Partial |
| Retention | Medium | Full |
| Crash rate | Medium | Full |
| Update frequency | Low | Full |

## Store Listing Elements

### Title (30 characters max)

**Structure:** Primary Keyword + Brand

| Good | Bad |
|------|-----|
| Task Manager - TodoFlow | TodoFlow: The Best Task Manager App |
| Photo Editor Pro | Photo App |
| Budget Tracker - MoneyWise | MW Budget |

**Tips:**
- Put main keyword first
- Include brand for recognition
- Use full 30 characters
- Test with A/B experiments

### Short Description (80 characters max)

First 2 lines visible without expansion. Must hook immediately.

**Structure:** Value prop + key feature + differentiator

```
Track expenses effortlessly. Smart categories, instant insights, no ads.
```

**Checklist:**
- [ ] Main keyword included
- [ ] Clear value proposition
- [ ] Differentiator from competitors
- [ ] No wasted words

### Full Description (4000 characters max)

**Structure:**
```
[Opening hook with main keyword - 2 lines]

[Key Features section - bullets]
★ Feature 1 - benefit
★ Feature 2 - benefit
★ Feature 3 - benefit

[Detailed paragraphs - keyword rich]

[Social proof - awards, press, numbers]

[Call to action]
```

**Keyword strategy:**
- Main keyword: 3-5 times naturally
- Secondary keywords: 2-3 times each
- Long-tail phrases in features
- Update quarterly based on Search Console

### Screenshots (up to 8 per device type)

| Position | Purpose | Best Practice |
|----------|---------|---------------|
| 1-2 | Hook | Best features, bold text |
| 3-4 | Features | Core functionality |
| 5-6 | Social proof | Reviews, awards, numbers |
| 7-8 | Details | Additional features |

**Requirements:**
- Phone: 16:9 or 9:16, min 320px, max 3840px
- Tablet 7": Same ratios
- Tablet 10": Same ratios

**Best practices:**
- Device frames optional but professional
- Bold headlines on each screenshot
- Consistent visual style
- Show real UI, not mockups
- Localize for major markets

### Feature Graphic (1024x500 required)

This appears in browse results and feature placements.

**Design rules:**
- No text smaller than 24pt
- Brand name prominent
- Don't rely on bottom 1/3 (gets cropped)
- Test at thumbnail size
- Avoid excessive text

### Video (optional, 30s-2min)

| Element | Recommendation |
|---------|----------------|
| Length | 30-60 seconds optimal |
| Hook | First 5 seconds critical |
| Format | Landscape, YouTube hosted |
| Content | Real app usage, not animations |
| Audio | Optional, caption if used |

## A/B Testing

### What to Test

| Element | Impact | Test Duration |
|---------|--------|---------------|
| Icon | High | 7 days |
| Screenshots | High | 7 days |
| Short description | Medium | 7 days |
| Feature graphic | Medium | 7 days |

### How to Run

1. Console → Store presence → Store listing experiments
2. Create experiment
3. Set variants (up to 3)
4. Choose traffic split
5. Run for 7+ days
6. Apply winner

### Metrics to Watch

| Metric | Good | Action if Bad |
|--------|------|---------------|
| First-time installers | > baseline | Keep variant |
| Store listing visitors | > baseline | Check keywords |
| Retained installers | > baseline | Fix onboarding |

## Keyword Research

### Tools

| Tool | Use For |
|------|---------|
| Play Console Search | Your actual search terms |
| AppTweak/Sensor Tower | Competitor keywords |
| Google Trends | Seasonal patterns |
| Google Ads Keyword Planner | Search volume |

### Process

1. **Seed list:** Features, use cases, problems solved
2. **Competitor scan:** Top 10 apps' descriptions
3. **Volume check:** Verify search volume
4. **Difficulty:** Can you rank? (smaller apps target long-tail)
5. **Implement:** Title > Short > Full description

### Refresh Cadence

| Element | Frequency |
|---------|-----------|
| Full description | Quarterly |
| Short description | Quarterly |
| Keywords analysis | Monthly |
| Screenshots | Every major feature |

## Localization

### Priority Markets

| Tier | Markets | Why |
|------|---------|-----|
| 1 | US, UK, India | Volume |
| 2 | Germany, Japan, Korea | High LTV |
| 3 | Brazil, Mexico, Indonesia | Growth |

### What to Localize

| Element | Priority |
|---------|----------|
| Title | Must |
| Short description | Must |
| Screenshots | Should |
| Full description | Should |
| Video | Nice to have |

### Localization Tips

- Don't just translate, localize
- Adjust screenshots for cultural context
- Research local competitors
- Local keyword research per market
- Native speakers for review


path: fastlane.md
content: # Fastlane Automation — Google Play Store

## Setup

### Install Fastlane

```bash
# macOS (Homebrew)
brew install fastlane

# Ruby (any platform)
gem install fastlane

# Verify
fastlane --version
```

### Service Account Setup

Google Play API requires a service account.

1. **Google Cloud Console:**
   - Create project or use existing
   - Enable Google Play Developer API
   - Create service account
   - Download JSON key

2. **Play Console:**
   - Settings → API access
   - Link Google Cloud project
   - Grant service account access
   - Set permissions (Release manager for uploads)

3. **Project Setup:**
```bash
cd android-project
fastlane init
```

4. **Configure Key:**
```bash
# In Fastfile or supply
supply(
  json_key: "path/to/key.json"
)
```

## Common Commands

### Upload to Internal Track

```bash
# AAB (recommended)
fastlane supply --aab app-release.aab --track internal

# APK
fastlane supply --apk app-release.apk --track internal
```

### Upload to Closed Testing

```bash
fastlane supply --aab app-release.aab --track beta
```

### Upload to Production (Staged)

```bash
# 10% rollout
fastlane supply --aab app-release.aab --track production --rollout 0.1

# Increase to 50%
fastlane supply --track production --rollout 0.5

# Full rollout
fastlane supply --track production --rollout 1.0
```

### Promote Between Tracks

```bash
# Internal to beta
fastlane supply --track_promote_to beta --track internal

# Beta to production (10%)
fastlane supply --track_promote_to production --track beta --rollout 0.1
```

### Update Store Listing

```bash
# Sync metadata from fastlane/metadata/android/
fastlane supply --skip_upload_aab --skip_upload_apk
```

## Fastfile Examples

### Basic Upload Lane

```ruby
# fastlane/Fastfile
lane :internal do
  gradle(task: "bundleRelease")
  supply(
    track: "internal",
    aab: "app/build/outputs/bundle/release/app-release.aab"
  )
end
```

### Full Release Lane

```ruby
lane :release do |options|
  # Build
  gradle(
    task: "bundleRelease",
    properties: {
      "android.injected.signing.store.file" => ENV["KEYSTORE_PATH"],
      "android.injected.signing.store.password" => ENV["KEYSTORE_PASSWORD"],
      "android.injected.signing.key.alias" => ENV["KEY_ALIAS"],
      "android.injected.signing.key.password" => ENV["KEY_PASSWORD"]
    }
  )
  
  # Upload with staged rollout
  supply(
    track: "production",
    rollout: options[:rollout] || 0.1,
    aab: "app/build/outputs/bundle/release/app-release.aab",
    skip_upload_metadata: true,
    skip_upload_images: true,
    skip_upload_screenshots: true
  )
end

# Usage: fastlane release rollout:0.2
```

### Metadata Sync Lane

```ruby
lane :metadata do
  supply(
    skip_upload_aab: true,
    skip_upload_apk: true,
    skip_upload_changelogs: false
  )
end
```

## Metadata Structure

```
fastlane/metadata/android/
├── en-US/                 # Locale folder
│   ├── title.txt          # App title (30 chars)
│   ├── short_description.txt  # 80 chars
│   ├── full_description.txt   # 4000 chars
│   ├── changelogs/
│   │   └── 123.txt        # versionCode changelog
│   └── images/
│       ├── phoneScreenshots/
│       ├── tenInchScreenshots/
│       └── featureGraphic.png
├── es-ES/                 # Spanish locale
└── de-DE/                 # German locale
```

## CI/CD Integration

### GitHub Actions

```yaml
name: Deploy to Play Store

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
          bundler-cache: true
      
      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
      
      - name: Decode Keystore
        run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 -d > keystore.jks
      
      - name: Decode Service Account
        run: echo "${{ secrets.PLAY_SERVICE_ACCOUNT }}" | base64 -d > service-account.json
      
      - name: Deploy to Internal
        env:
          KEYSTORE_PATH: keystore.jks
          KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
        run: fastlane internal
```

### GitLab CI

```yaml
deploy_internal:
  stage: deploy
  image: cimg/android:2024.01
  script:
    - echo "$KEYSTORE_BASE64" | base64 -d > keystore.jks
    - echo "$PLAY_SERVICE_ACCOUNT" | base64 -d > service-account.json
    - gem install fastlane
    - fastlane internal
  only:
    - tags
```

## Troubleshooting

### Authentication Errors

```
Error: Google Api Error: forbidden
```

**Fixes:**
1. Check service account has correct permissions in Play Console
2. Verify JSON key path is correct
3. Check API is enabled in Google Cloud Console
4. Wait 24h after granting permissions

### Track Errors

```
Error: Cannot rollout to production before testing
```

**Fix:** Complete 20 testers + 14 days requirement first.

### Version Code Errors

```
Error: Version code already used
```

**Fix:** Increment versionCode. Cannot reuse even for rejected builds.

### Upload Timeouts

```
Error: Request timed out
```

**Fixes:**
1. Check file size (AAB should be < 150MB)
2. Check network connection
3. Try again (transient server issue)

## Best Practices

| Practice | Why |
|----------|-----|
| AAB over APK | Smaller downloads, Google manages signing |
| Semantic versioning | Easy to track releases |
| Automated changelogs | Consistent, error-free |
| Staged rollouts | Catch issues before full release |
| Store secrets in CI | Never commit keys |
| Separate lanes | internal vs production clarity |


path: memory-template.md
content: # Memory Template — Google Play Store

Create `~/google-play-store/memory.md` with this structure:

```markdown
# Google Play Store Memory

## Status
status: ongoing
version: 1.0.0
last: YYYY-MM-DD
integration: pending

## Workflow
<!-- Organization name, team size, release cadence -->
<!-- NO credentials, keys, or secrets here -->

## Apps
<!-- Package names and high-level status -->
<!-- com.example.app - production, stable -->
<!-- com.example.beta - closed testing -->

## CI/CD
<!-- Manual uploads vs CI/CD -->
<!-- Tool names only: Fastlane, GitHub Actions, etc. -->
<!-- NO secrets, tokens, or passwords stored here -->

## Preferences
<!-- Release cadence, rollout strategy -->
<!-- Notification preferences -->

## Lessons Learned
<!-- Past rejections and how they were fixed -->
<!-- Gotchas specific to their apps -->

---
*Updated: YYYY-MM-DD*
```

## Per-App Notes

For each app, create `~/google-play-store/apps/{package-name}.md`:

```markdown
# {App Name}

## Info
package: com.example.app
track: production
signing: google-managed
target_sdk: 34

## Releases
<!-- Recent release history -->
- YYYY-MM-DD: v1.2.0 (versionCode 2025022501)
- YYYY-MM-DD: v1.1.0 rollout halted at 5%

## Rejections
<!-- If any, with resolution -->

## ASO
<!-- Keywords tracking, screenshot strategy -->

## Notes
<!-- App-specific observations -->
```

## Status Values

| Value | Meaning | Behavior |
|-------|---------|----------|
| `ongoing` | Still learning | Gather context from conversations |
| `complete` | Enough context | Work normally |
| `paused` | User said "not now" | Don't ask, use what you have |

## Key Principles

- Learn from conversations, don't interrogate
- Update `last` on each interaction
- Most users stay `ongoing` indefinitely


path: policies.md
content: # Policy Compliance — Google Play Store

## Data Safety Section

### Required for ALL Apps

Even if your app collects nothing, you MUST complete the form.

| Question | If You Don't Collect |
|----------|---------------------|
| Does your app collect data? | Select "No" |
| Does your app share data? | Select "No" |
| Security practices | Still complete this |

### Data Types to Declare

| Category | Examples | If Using Analytics SDK |
|----------|----------|----------------------|
| Location | GPS, IP-based | Probably yes |
| Personal info | Name, email, phone | If login exists |
| Financial | Payment, purchase history | If IAP exists |
| Health & fitness | Steps, heart rate | If fitness app |
| Messages | SMS, chat | If messaging |
| Photos/videos | Camera, gallery access | If media app |
| Audio | Mic recordings | If voice features |
| Files | Docs, downloads | If file access |
| App activity | Views, taps, interactions | Almost always yes |
| Device IDs | AAID, IMEI | If analytics |
| Diagnostics | Crash logs, performance | Almost always yes |

### Common SDKs and Their Data

| SDK | Collects |
|-----|----------|
| Firebase Analytics | App activity, device ID, diagnostics |
| Crashlytics | Diagnostics, device info |
| Google Ads | Device ID, app activity |
| Facebook SDK | Device ID, app activity, personal info |
| AppsFlyer | Device ID, app activity |

**Rule:** If you use an SDK, read its data disclosure docs.

## Permissions

### Dangerous Permissions

| Permission | Scrutiny | Required Justification |
|------------|----------|----------------------|
| CAMERA | High | Show camera feature in screenshots |
| LOCATION | High | Core feature, explain in description |
| MICROPHONE | High | Core feature, explain in description |
| CONTACTS | Very High | Rarely approved, must be essential |
| CALL_LOG | Very High | Default dialer apps only |
| SMS | Very High | Default SMS apps only |
| STORAGE | Medium | Scoped storage preferred |
| BODY_SENSORS | High | Health apps with justification |

### Background Location

**Extra requirements:**
- Declaration form with video showing feature
- Must be core to app function
- Prominent in-app disclosure
- User consent before request

**If rejected:** Remove the permission or become a location-focused app.

### Permission Declaration Form

Console → Policy → App content → Permissions

For each sensitive permission:
1. Describe exactly how used
2. Link to feature in app
3. Provide video demonstration
4. Explain why runtime alternatives don't work

## Content Rating

### Questionnaire Topics

| Topic | Truthful Answers |
|-------|-----------------|
| Violence | Mild cartoon, realistic combat, blood |
| Sexual content | Nudity, suggestive, explicit |
| Language | Profanity level |
| Substances | Drugs, alcohol, tobacco |
| Gambling | Real money, simulated |
| User interaction | Chat, sharing, user content |

### Consequences of Underrating

| Issue | Consequence |
|-------|-------------|
| User reports mature content | Review + potential strike |
| Age-restricted content undeclared | App removal |
| COPPA violation (kids) | Legal liability |

### Updating Rating

Required when you add:
- User-generated content
- Chat features
- Mature themes
- Gambling elements

## Target Audience

### Children Apps

If ANY appeal to children under 13:

| Requirement | Details |
|-------------|---------|
| Families Policy | Strict ad rules apply |
| Teacher Approved | Optional certification |
| Content restrictions | No mature themes |
| Behavioral targeting | Prohibited |
| Personal data | Minimal, with consent |

### Safe Declaration

If NOT targeting children:
- Console → App content → Target audience
- Select "Not designed for children"
- Don't use child-appealing elements

## API Requirements

### Target SDK (2024)

| Deadline | Requirement |
|----------|-------------|
| Aug 2024 | API 34 for new apps |
| Nov 2024 | API 34 for updates |

### Deprecated APIs

| API | Status | Alternative |
|-----|--------|-------------|
| MANAGE_EXTERNAL_STORAGE | Restricted | Scoped storage, SAF |
| REQUEST_INSTALL_PACKAGES | Restricted | Play Feature Delivery |
| QUERY_ALL_PACKAGES | Restricted | Declare specific packages |
| Non-SDK interfaces | Blocked | Use public APIs |

## Advertising Policies

### Interstitial Ads

| Rule | Requirement |
|------|-------------|
| Close button | Visible within 5 seconds |
| Timing | Not during app loading |
| Frequency | Cannot impair usability |
| After IAP | Prohibited |
| Lock screen | Prohibited |

### Rewarded Ads

| Rule | Requirement |
|------|-------------|
| User consent | Must be opt-in |
| Clear exchange | Show what user gets |
| Delivery | Must deliver reward |

### Deceptive Ads

**Prohibited:**
- Fake system alerts
- Fake close buttons
- Auto-redirects
- Ads mimicking app UI

**Consequence:** Strike or suspension

## Account Standing

### Warning Levels

| Level | Impact | Recovery |
|-------|--------|----------|
| Warning | Notice only | Acknowledge |
| Strike | Feature restrictions | Time-based decay |
| Suspension | App removed | Appeal |
| Termination | Account closed | Nearly impossible |

### Strike Triggers

| Violation | Severity |
|-----------|----------|
| Policy violation (first) | Warning or strike |
| Repeat violation | Strike |
| Malware | Immediate suspension |
| Deceptive behavior | Strike or suspension |
| Impersonation | Suspension |
| Illegal content | Termination |

### Maintaining Standing

1. Respond to policy emails within 7 days
2. Never create accounts to evade enforcement
3. Fix issues before escalation
4. Use Policy Center for guidance
5. Appeal with evidence, not emotion


path: rejections.md
content: # Rejection Recovery — Google Play Store

## Rejection vs Suspension

| Type | Meaning | Action |
|------|---------|--------|
| Rejection | This upload declined | Fix and resubmit |
| Removal | App pulled from store | Fix, resubmit, appeal |
| Suspension | Account restricted | Appeal required |
| Termination | Account closed | Very difficult to recover |

## Common Rejections

### 1. Testing Requirements Not Met

**Message:** "You must have at least 20 testers who have opted in and tested your app for at least 14 days"

**Fix:**
1. Go to Closed testing in Console
2. Verify 20+ testers have OPTED IN (check "Opted in" column)
3. Wait until 14 days from first opt-in
4. Then promote to production

**Prevention:** Start closed testing on day 1 of development.

### 2. Data Safety Form Incomplete

**Message:** "Complete the Data safety form in Play Console"

**Fix:**
1. Console → Policy → App content → Data safety
2. Answer EVERY question
3. If you use ANY analytics SDK, declare data collection
4. Submit for review

**Common mistake:** "We don't collect data" but using Firebase/Crashlytics.

### 3. Target SDK Too Low

**Message:** "Your app currently targets API level X and must target at least Y"

**Fix:**
```gradle
android {
    defaultConfig {
        targetSdkVersion 34
    }
}
```

Rebuild and resubmit.

### 4. Policy Violation - Permissions

**Message:** "Your app requests sensitive permissions without adequate justification"

**Fix:**
1. Console → Policy → App content → Permissions
2. Provide detailed justification for each permission
3. Include video showing permission in use
4. OR remove the permission

**For background location:**
- Must be core feature
- Prominent disclosure in app
- Video showing real usage

### 5. Store Listing Violations

**Message:** "Your store listing contains [specific issue]"

| Issue | Fix |
|-------|-----|
| Keyword stuffing | Rewrite naturally |
| Misleading screenshots | Use real app screenshots |
| Fake ratings claim | Remove claims |
| Trademark issue | Remove trademarked terms |

### 6. Functionality Issues

**Message:** "App crashes" or "App doesn't work as described"

**Debug:**
1. Download the exact APK/AAB you uploaded
2. Test on stock Android device
3. Test on Android 14 (API 34)
4. Test without network
5. Check Console for crash reports

**Common causes:**
- Missing null checks
- API key not working in release build
- Server issues during review
- Obfuscation broke something

### 7. Deceptive Behavior

**Message:** "Your app engages in deceptive behavior"

| Trigger | Fix |
|---------|-----|
| Hidden functionality | Disclose all features |
| Misleading ads | Follow ad policies |
| False claims | Remove or verify claims |
| Impersonation | Differentiate from other apps |

**This is serious.** May come with strike.

### 8. Intellectual Property

**Message:** "Your app infringes on intellectual property"

| Issue | Fix |
|-------|-----|
| Trademarked name | Rename app |
| Copyrighted assets | Remove or license |
| Clone of another app | Differentiate significantly |

## Appeal Process

### When to Appeal

- You believe rejection was wrong
- You've fixed the issue
- You need clarification on the rejection

### How to Appeal

1. Console → Inbox → Find rejection email
2. Click "Appeal" or "Request review"
3. Provide clear, factual response:
   - What the issue was
   - What you changed
   - Evidence of fix
4. Submit and wait 3-7 days

### Appeal Template

```
Summary: [What happened]

Changes Made:
1. [Specific change 1]
2. [Specific change 2]

Evidence:
- [Screenshot/link showing fix]
- [Video if applicable]

Request: Please review the updated submission.
```

### Appeal Tips

| Do | Don't |
|----|-------|
| Be factual | Be emotional |
| Show evidence | Make excuses |
| Address exact issue | Go off-topic |
| Be concise | Write essays |
| Respond once | Spam appeals |

## Suspension Recovery

### If App is Suspended

1. **Read the email carefully** — understand exact violation
2. **Don't panic-create new account** — that gets you terminated
3. **Check all your apps** — might be account-level issue
4. **Document everything** — screenshots, communications

### Suspension Appeal

1. Console → Policy status → Request appeal
2. Explain what happened
3. Show how you've fixed it
4. Commit to compliance going forward
5. Wait 2-4 weeks

### If Appeal Denied

Options (in order of preference):
1. Fix more thoroughly, appeal again (limit applies)
2. Consult legal if you believe Google erred
3. New developer account (last resort, risky)

**New account risks:** If Google connects accounts, both get terminated.

## Prevention Checklist

Run before EVERY submission:

```
STORE LISTING
[ ] No trademark violations
[ ] Screenshots show real app
[ ] No misleading claims
[ ] Privacy policy URL works

CONTENT
[ ] Data safety form complete
[ ] Content rating done
[ ] Permissions justified
[ ] Target SDK ≥ 34

TESTING
[ ] Tested on API 34 device
[ ] No crashes on fresh install
[ ] All features work without login (or clear onboarding)
[ ] Network error handling works

NEW APPS ONLY
[ ] 20+ testers opted in
[ ] 14+ days of testing completed
```

## Severity Guide

| Violation Type | Typical Outcome |
|----------------|-----------------|
| Technical (crashes) | Rejection, fix and resubmit |
| Metadata (keywords) | Rejection, fix listing |
| Policy (first time) | Warning or strike |
| Policy (repeat) | Strike, possible removal |
| Malware/deceptive | Immediate suspension |
| Repeat severe | Termination |


path: setup.md
content: # Setup — Google Play Store

Read this when `~/google-play-store/` doesn't exist or is empty. Start the conversation naturally.

## Your Attitude

You're the Play Store expert. Help them avoid the pitfalls that trip up most developers. Be proactive about the requirements they probably don't know about.

## Priority Order

### 1. First: Integration (within first 2-3 exchanges)

Figure out when this skill should activate:
- "Want me to help whenever you mention Play Store, Android releases, or app publishing?"
- "Should I remind you about policy updates that might affect your apps?"

Save their preference to `~/google-play-store/memory.md`.

### 2. Then: Understand Their Situation

Key questions:
- Do they have apps on Play Store already?
- New app or managing existing?
- What's their release cadence?
- Any past rejections or policy issues?
- Using CI/CD or manual uploads?

After each answer, reflect what you learned and how you'll help.

### 3. Finally: App-Specific Setup

If they have specific apps:
- Package name (com.company.app)
- Current track status
- Signing model (Google-managed vs upload key)
- Known issues or goals

## What You're Saving

In `~/google-play-store/memory.md`:
- Integration preferences
- Apps they manage
- Their workflow (CI/CD vs manual)
- Past issues and lessons learned

In `~/google-play-store/apps/{package}/`:
- Per-app notes
- Submission history
- Rejection recovery notes

## First-Time Warnings

For new Play Store publishers, proactively mention:
1. **20-tester requirement** — Start closed testing immediately
2. **14-day requirement** — Cannot skip, plan around it
3. **Data safety form** — Fill completely before first submission
4. **Upload key backup** — Do it now, store securely

These trip up 90% of first-time publishers.


path: tracks.md
content: # Release Tracks — Google Play Store

## Track Hierarchy

```
┌─────────────────────────────────────────────────────────────┐
│  INTERNAL          100 users max, instant, QA builds       │
├─────────────────────────────────────────────────────────────┤
│  CLOSED            Email list, 2-6h review, beta testers   │
├─────────────────────────────────────────────────────────────┤
│  OPEN              Anyone joins, 2-6h review, public beta  │
├─────────────────────────────────────────────────────────────┤
│  PRODUCTION        Everyone, 2-24h review, full release    │
└─────────────────────────────────────────────────────────────┘
```

## New App Requirements (Critical)

Google enforces before FIRST production release:

| Requirement | Details |
|-------------|---------|
| Closed testers | Minimum 20 must OPT IN (invited ≠ opted in) |
| Testing period | 14 consecutive days of testing activity |
| Data safety | Form must be 100% complete |
| Content rating | Questionnaire completed |

**Check status:** Console → Release → Closed testing → Testers

### Timeline Planning

```
Day 1:   Upload to internal, QA
Day 2:   Fix critical bugs
Day 3:   Upload to closed, invite 25+ testers
Day 4-7: Testers install and use
Day 7:   Check 20+ have opted in
Day 8-16: Continue closed testing
Day 17:  Requirements met, promote to production
Day 18+: Production review (2-24h)
```

**Start closed testing immediately when app is usable.**

## Staged Rollouts

### Production Rollout Stages

| Percentage | Duration | What to Watch |
|------------|----------|---------------|
| 1% | 24-48 hours | Crashes, critical bugs |
| 5% | 48-72 hours | ANRs, performance |
| 20% | 72-96 hours | User feedback, ratings |
| 50% | 96-120 hours | Stability at scale |
| 100% | — | Full release |

### Rollout Controls

**Increase rollout:**
Console → Release → Production → Manage release → Edit rollout percentage

**Halt rollout:**
Console → Release → Production → Halt rollout
- Users who updated keep the update
- New users get previous stable version
- Can resume or upload new release

**Rollback:**
Upload previous version with NEW versionCode, rollout to 100%

### Halt Triggers

Stop rollout immediately if:
- Crash rate > 1% (vs previous version)
- ANR rate > 0.5%
- Sudden spike in 1-star reviews
- Critical functionality broken
- Security vulnerability discovered

## Track-Specific APKs

Different tracks CAN have different APKs:

| Track | Example Config |
|-------|----------------|
| Internal | debuggable, verbose logging, test endpoints |
| Closed | release build, analytics verbose, staging API |
| Production | release build, production API, optimized |

**Requirements:**
- Each APK needs unique versionCode
- Can't promote APK to track with lower versionCode already there
- Production APK should match what was tested

## Country Targeting

### Per-Track Availability

| Track | Typical Countries |
|-------|-------------------|
| Internal | Worldwide (dev team) |
| Closed | Home country + test markets |
| Open | Target launch markets |
| Production | Final market list |

### Staged Geographic Rollout

1. Launch in 1-3 countries first
2. Monitor metrics for 2 weeks
3. Expand to similar markets
4. Go global

**Why:** Catch localization issues, server scaling problems, regional policy issues.

## Track Management Commands

### Using bundletool

```bash
# Build AAB
./gradlew bundleRelease

# Upload to internal track
# (Use Play Console or Fastlane - API requires service account)
```

### Using Fastlane

```bash
# Upload to internal
fastlane supply --aab app.aab --track internal

# Promote internal to beta
fastlane supply --track_promote_to beta --track internal

# Production with staged rollout
fastlane supply --aab app.aab --track production --rollout 0.01
```

## Common Track Mistakes

| Mistake | Consequence | Prevention |
|---------|-------------|------------|
| Skip closed testing | Cannot promote to production | Start testing day 1 |
| Promote before 14 days | Blocked | Calendar reminder |
| Same APK to multiple tracks | Confusing version state | Unique versionCodes |
| 100% rollout on day 1 | Bad update hits everyone | Always stage |


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)