wger Documentation

Self hosted FLOSS fitness/workout, nutrition and weight tracker

7,159 stars Python Python 11 files Β· ~7,667 tokens #django#fitness#gym#hacktoberfest#python#self-hosted#workout
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy wger on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name wger -p 27017:27017 --restart always mongo
Configured Services & Ports
βš™οΈ mongodb
image: mongo
πŸ”Œ Ports: 27017:27017
βš™οΈ mongo-express
image: mongo-express
πŸ”Œ Ports: 8081:8081
docker-compose.yml
yaml (docker-compose.yml)
services:
  mongodb:
    image: mongo
    ports:
      - "27017:27017"
    volumes:
      - $PWD/dump/dump:/dump
    environment:
      MONGO_INITDB_ROOT_USERNAME: off
      MONGO_INITDB_ROOT_PASSWORD: off-wger

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: off
      ME_CONFIG_MONGODB_ADMINPASSWORD: off-wger
      ME_CONFIG_MONGODB_URL: mongodb://off:off-wger@mongodb:27017/

Technical Documentation: wger-project/wger

ℹ️ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference

Overview (`README.md`)

wger

wger (ˈvɛɑɐ) is a free workout and fitness manager.

  • πŸ‹οΈ Custom Workout Routines – Create flexible routines with automatic weight progression rules.
  • πŸ“Š Comprehensive Tracking – Track diet plans, body weight, and custom measurements.
  • 🍽️ Nutrition Management – Log your calories with a food database
    from Open Food Facts.
  • πŸ“Έ Progress Gallery – Upload and track your fitness progress with photos.
  • πŸ“š Exercise Wiki – Access and contribute to the built-in exercises.
  • πŸ“± Cross-Platform Apps – Available on
    Android,
    iOS,
    F-Droid,
    and Flathub.
  • 🐳 Self-Hostable – Deploy easily with Docker for full control.
  • 🌍 Multilingual Support – Translated by the community via Weblate.
  • πŸ”— Powerful API – REST API for third-party integrations or automations.
  • πŸ‘₯ Multi-User Support – Includes basic gym management features.
  • πŸ†“ 100% Free & Open Source – Licensed under AGPL-3.0 or later.

For a live system, visit: https://wger.de

Self-hosting

Hosting your own instance is basically just a docker compose up -d away. For
more detailed setup instructions take a look at the provided
docker compose file and the
corresponding documentation.

Developing and contributing

Our goal is to build an awesome and flexible fitness and nutrition manager,
along with a comprehensive list of exercises and ingredients, all released
under a free license.

For this, we’d love your help! Whether it’s code, translations, exercises or
reporting issues and ideas, check out our
contribution guide
to get started.

A huge thank you to everyone who has contributed so far! ❀️ See the full list
in AUTHORS.md.

Documentation

Consult the online documentation at

for installation instructions, API documentation, development guidelines, and
other information

Contact

Feel free to contact us if you found this useful or if there was something that
didn't behave as you expected. We can't fix what we don't know about, so please
report liberally. If you're not sure if something is a bug or not, feel free to
file a bug anyway.

Sources

All the code and the content is available on github:

Translation

Translate the app to your language on Weblate.

License


Overview (`settings/README.md`)

Settings

This directory contains configuration files and settings for the project.

You can add your own configuration files here, e.g. for development. Set
the DJANGO_SETTINGS_MODULE environment variable to point to the new settings
file. E.g.:

bash
export DJANGO_SETTINGS_MODULE=settings.local_dev
python manage.py runserver

If you want to add settings that are not tracked by git, you can create a
local_dev_extra.py file, this will be imported by local_dev.py if it exists.


Overview (`extras/authors/README.md`)

Generate authors list

This small script reads the commit information and generates a list of authors
and links them to their GitHub profile, if available. This can be run before
each release to keep the data up to date.

Usage

Note that you might run into rate-limiting issues if you run this script too
often. If so, you can generate a token and use it in the script:
https://github.com/settings/personal-access-tokens (no need to select any
permissions, we're just performing reading operations on public data)

Run the script and optionally copy the generated files to their correct locations

bash
uv run generate_authors_api.py

Overview (`extras/open-food-facts/README.md`)

Import Open Food Facts products

This docker compose helps import or update products from the Open Food Facts
database into wger.

Note that the OFF database dump is very large, and you will need several times
this size available on your computer (tar.gz-file, extracted dump, mongo).

1

Download a current dump of their database

shell
cd dump
wget https://static.openfoodfacts.org/data/openfoodfacts-mongodbdump.tar.gz
tar xzvf openfoodfacts-mongodbdump.tar.gz

2

Import the data into mongo.

Note that we are running this as a manual step since the import takes a while

shell
docker compose up
docker compose exec mongodb mongorestore --username off --password off-wger -d admin -c products /dump/off/products.bson

There is also an admin interface available at http://localhost:8081, log in with
these credentials:

  • admin
  • pass

3

Run the import script

shell
python manage.py import-off-products

To update the data fixtures:

shell
python manage.py dumpdata nutrition > extras/scripts/data.json
cd extras/scripts
python filter-fixtures.py
zip ingredients.json.zip ingredients.json 
zip weight_units.json.zip weight_units.json
zip ingredient_units.json.zip ingredient_units.json

4

Don't forget to delete the dump and remove the containers if you love your
hard disk

shell
docker compose down
rm dump -r openfoodfacts-mongodbdump.tar.gz dump/dump

Overview (`wger/trophies/README.md`)

Trophy System

The trophy (achievement) system allows users to earn trophies based on
their workout activities.

Features

  • Multiple Trophy Types: Time-based, volume-based, count-based,
    sequence-based, date-based, and custom trophies
  • Progressive Trophies: Show user progress towards earning a trophy
  • Hidden Trophies: Secret achievements that are revealed only when
    earned
  • Repeatable Trophies: Trophies can be earned multiple times, for
    example PR trophies. Context data can be added to each earned trophy.
  • Automatic Evaluation: Trophies are evaluated automatically when
    workout data changes
  • Statistics Tracking: Denormalized statistics for efficient trophy
    evaluation
  • API Endpoints: Full REST API for trophy data and progress tracking

Configuration

Global Settings

Add to your settings.py or settings_global.py:

python
WGER_SETTINGS = {
    # Enable/disable the trophy system globally
    'TROPHIES_ENABLED': True,
    # Number of days of inactivity before skipping trophy evaluation for a user
    'TROPHIES_INACTIVE_USER_DAYS': 30,
}

User Preferences

Users can enable/disable trophies in their profile settings via the
trophies_enabled field on UserProfile.

Database Models

Trophy

Defines an achievement that users can earn.

Fields:

  • name: Trophy name
  • description: How to earn it
  • trophy_type: Type (time, volume, count, sequence, date, other)
  • checker_class: Python class that checks if trophy is earned
    (e.g., 'count_based')
  • checker_params: JSON parameters for the checker
    (e.g., {'count': 10})
  • is_hidden: Hidden until earned
  • is_progressive: Shows progress percentage
  • is_active: Can be earned (admins can disable)
  • is_repeatable: Can be earned multiple times
  • order: Display order

UserTrophy

Links users to their earned trophies.

Fields:

  • user: User who earned the trophy
  • trophy: The trophy earned
  • earned_at: Timestamp when earned
  • progress: Progress percentage (0-100)
  • is_notified: For future notification system
  • context_data: Additionnal information on the trophy

UserStatistics

Denormalized statistics for efficient trophy checking.

Fields:

  • user: OneToOne with User
  • total_weight_lifted: Cumulative weight in kg
  • total_workouts: Number of workout sessions
  • current_streak: Current consecutive workout days
  • longest_streak: Longest streak ever achieved
  • earliest_workout_time: Earliest workout time ever
  • latest_workout_time: Latest workout time ever
  • weekend_workout_streak: Consecutive weekends with workouts
  • last_complete_weekend_date: Last Saturday with both days worked
  • worked_out_jan_1: Has worked out on any January 1st
  • last_inactive_date: Last workout before 30+ day gap

Trophy Checkers

Trophy checkers are Python classes that determine if a user has earned a trophy.

Available Checkers

  1. count_based: Check if user reached a count

    • Params: {'count': 10}
    • Example: "Complete 10 workouts"
  2. streak: Check for consecutive day streaks

    • Params: {'days': 30}
    • Example: "30-day workout streak"
  3. weekend_warrior: Check for consecutive complete weekends

    • Params: {'weekends': 4}
    • Example: "Work out on Saturday AND Sunday for 4 weekends"
  4. volume: Check for cumulative weight lifted

    • Params: {'kg': 5000}
    • Example: "Lift 5,000 kg total"
  5. time_based: Check for workout at specific time

    • Params: {'before': '06:00'} or {'after': '21:00'}
    • Example: "Work out before 6:00 AM"
  6. date_based: Check for workout on specific date

    • Params: {'month': 1, 'day': 1}
    • Example: "Work out on January 1st"
  7. inactivity_return: Check for return after inactivity

    • Params: {'inactive_days': 30}
    • Example: "Return to training after 30 days inactive"
  8. personal_record: Check for new PRs

    • Params: {'log': WorkoutLog}
    • Example: "Beats PR on exercise 'Bench Press Dumbells' by logging 100kg for 10 reps."

Management Commands

Load Trophies

Load the initial set of trophies into the database:

bash
# Load trophies (overwrites existing ones if IDs match)
python manage.py loaddata initial_trophies

Evaluate Trophies

Manually trigger trophy evaluation:

bash
# Evaluate for a specific user
python manage.py evaluate_trophies --user username

# Evaluate a specific trophy for all users
python manage.py evaluate_trophies --trophy 5

# Evaluate all trophies for all active users
python manage.py evaluate_trophies --all

# Force re-evaluation (check already earned trophies)
python manage.py evaluate_trophies --all --force-reevaluate

Recalculate Statistics

Rebuild user statistics from workout history:

bash
# Recalculate for a specific user
python manage.py recalculate_statistics --user username

# Recalculate for all users
python manage.py recalculate_statistics --all

# Recalculate for active users only
python manage.py recalculate_statistics --all --active-only

API Endpoints

Trophy Endpoints

text
GET /api/v2/trophy/
    List all active trophies
    - Hidden trophies excluded unless earned by user

GET /api/v2/trophy/{id}/
    Get specific trophy details

GET /api/v2/trophy/progress/
    Get progress for all trophies (current user)
    - Returns earned status and progress percentage
    - Includes current/target values for progressive trophies

User Trophy Endpoints

text
GET /api/v2/user-trophy/
    List current user's earned trophies
    - Ordered by earned_at (newest first)

GET /api/v2/user-trophy/{id}/
    Get specific earned trophy details

User Statistics Endpoints

text
GET /api/v2/user-statistics/
    Get current user's trophy statistics

API Components

Serializers

TrophySerializer (wger.trophies.api.serializers):

  • Serializes Trophy model for API responses
  • Fields: id, uuid, name, description, trophy_type, checker_class,
    checker_params, is_hidden, is_progressive, is_active, order
  • Read-only serializer for trophy definitions

UserTrophySerializer (wger.trophies.api.serializers):

  • Serializes UserTrophy model (earned trophies)
  • Fields: id, user, trophy (nested), earned_at, progress, is_notified
  • Includes nested trophy details in response

UserStatisticsSerializer (wger.trophies.api.serializers):

  • Serializes UserStatistics model
  • Fields: All statistics fields (total_weight_lifted, total_workouts,
    current_streak, longest_streak, etc.)
  • Read-only serializer for statistics data

TrophyProgressSerializer (wger.trophies.api.serializers):

  • Custom serializer for trophy progress tracking
  • Fields: trophy (nested), is_earned, earned_at, progress,
    current_value, target_value
  • Used by /api/v2/trophy/progress/ endpoint

Filtersets

TrophyFilterSet (wger.trophies.api.filtersets):

  • Filter trophies by type, active status, hidden status
  • Fields: trophy_type, is_active, is_hidden, is_progressive
  • Example: /api/v2/trophy/?trophy_type=volume&is_active=true

UserTrophyFilterSet (wger.trophies.api.filtersets):

  • Filter user's earned trophies
  • Fields: trophy, earned_at (date range), progress
  • Example: /api/v2/user-trophy/?trophy=5&earned_at__gte=2024-01-01

Example API Usage:

python
# Get all volume-based trophies
GET /api/v2/trophy/?trophy_type=volume

# Get trophies earned in 2024
GET /api/v2/user-trophy/?earned_at__year=2024

# Get progress for all trophies (authenticated)
GET /api/v2/trophy/progress/

# Get current user's statistics
GET /api/v2/user-statistics/

Adding New Trophies

  1. Create a new checker class (if needed) in wger/trophies/checkers/:
python
# wger/trophies/checkers/my_checker.py
from .base import BaseTrophyChecker


class MyCustomChecker(BaseTrophyChecker):
    def check(self) -> bool:
        # Your logic here
        return True

    def get_progress(self) -> float:
        # Calculate progress 0-100
        return 50.0

    def get_current_value(self):
        return 'current'

    def get_target_value(self):
        return 'target'
  1. Register the checker in wger/trophies/checkers/registry.py:
python
from .my_checker import MyCustomChecker


class CheckerRegistry:
    _registry: Dict[str, Type[BaseTrophyChecker]] = {
        # ... existing checkers ...
        'my_custom': MyCustomChecker,
    }
  1. Add the trophy via Django admin or shell:
python
from wger.trophies.models import Trophy

Trophy.objects.create(
    name='My Custom Trophy',
    description='Description of how to earn it',
    trophy_type=Trophy.TYPE_OTHER,
    checker_class='my_custom',
    checker_params={'param1': 'value1'},
    is_hidden=False,
    is_progressive=True,
    order=100,
)

Method 2: Using Existing Checkers

Simply create a new Trophy object with an existing checker:

python
Trophy.objects.create(
    name='Heavy Lifter',
    description='Lift 10,000 kg total',
    trophy_type=Trophy.TYPE_VOLUME,
    checker_class='volume',
    checker_params={'kg': 10000},
    is_progressive=True,
    order=50,
)

Method 3: Using Fixtures

Create a JSON fixture in wger/trophies/fixtures/:

json
[
  {
    "model": "trophies.trophy",
    "pk": 10,
    "fields": {
      "name": "My Trophy",
      "description": "Description",
      "trophy_type": "count",
      "checker_class": "count_based",
      "checker_params": {"count": 100},
      "is_hidden": false,
      "is_progressive": true,
      "is_active": true,
      "order": 100
    }
  }
]

Load with: python manage.py loaddata my_trophies

Services API

UserStatisticsService

Service for managing user workout statistics.

Methods:

  • increment_workout(user, workout_date, weight_lifted): Incrementally
    update statistics after a workout. Updates streak, total workouts,
    weight lifted, and workout times.
  • update_statistics(user): Recalculate all statistics from scratch
    by scanning workout history. Use for fixing inconsistencies.
  • get_or_create_statistics(user): Get existing statistics or create
    new record with default values.
  • handle_workout_deletion(user, workout_date): Update statistics
    after a workout is deleted. Recalculates streaks if needed.

Example Usage:

python
from wger.trophies.services.statistics import UserStatisticsService
from decimal import Decimal
import datetime

# Increment after workout
UserStatisticsService.increment_workout(
    user=request.user, workout_date=datetime.date.today(), weight_lifted=Decimal('150.5')
)

# Recalculate all statistics
stats = UserStatisticsService.update_statistics(request.user)

# Get statistics (create if missing)
stats = UserStatisticsService.get_or_create_statistics(request.user)

TrophyService

Service for evaluating and awarding trophies.

Methods:

  • evaluate_all_trophies(user, force=False): Evaluate all active
    trophies for a user. Returns list of newly awarded UserTrophy
    objects. Skip already earned unless force=True.
  • award_trophy(user, trophy, progress=100.0): Award a specific
    trophy to a user. Creates UserTrophy record. Idempotent (safe to
    call multiple times).
  • get_user_trophies(user, include_hidden=False): Get all trophies
    earned by a user. Filter hidden trophies unless specified.
  • get_all_trophy_progress(user, include_hidden=False): Get progress
    for all trophies. Returns list of dicts with trophy info, earned
    status, progress %, current/target values.
  • reevaluate_trophies(user_ids=None, trophy_id=None, force_reevaluate=False): Batch re-evaluate trophies for multiple
    users. Returns dict with users_checked, trophies_awarded counts.

Example Usage:

python
from wger.trophies.services.trophy import TrophyService

# Evaluate all trophies for user
newly_awarded = TrophyService.evaluate_all_trophies(request.user)
for user_trophy in newly_awarded:
    print(f'Earned: {user_trophy.trophy.name}')

# Get user's earned trophies
earned = TrophyService.get_user_trophies(request.user)

# Get progress for all trophies
progress = TrophyService.get_all_trophy_progress(request.user)
for item in progress:
    print(f'{item["trophy"].name}: {item["progress"]}%')

# Batch re-evaluate for all active users
results = TrophyService.reevaluate_trophies()
print(f'Checked {results["users_checked"]} users')
print(f'Awarded {results["trophies_awarded"]} trophies')

Signals and Auto-Evaluation

Signal Handlers

The trophy system uses Django signals for automatic evaluation:

workout_log_saved signal (wger.manager.signals):

  • Fires when WorkoutLog is saved (user logs exercise sets)
  • Handler: Updates UserStatistics incrementally
  • Then evaluates all trophies for the user

workout_session_saved signal (wger.manager.signals):

  • Fires when WorkoutSession is saved (user completes workout)
  • Handler: Updates workout count and streak
  • Then evaluates all trophies for the user

workout_deleted signal (wger.manager.signals):

  • Fires when workout is deleted
  • Handler: Calls handle_workout_deletion() to update statistics

Configuration:

Signals are automatically connected in wger/trophies/apps.py:

python
class TrophiesConfig(AppConfig):
    def ready(self):
        import wger.trophies.signals  # noqa: F401

How Auto-Evaluation Works

When a user logs a workout:

  1. WorkoutSession or WorkoutLog is saved
  2. Django signal fires (post_save)
  3. UserStatisticsService.increment_workout() updates statistics
    incrementally
  4. TrophyService.evaluate_all_trophies() checks for newly earned
    trophies
  5. Earned trophies create UserTrophy records
  6. User sees new trophy (notifications in future version)

Celery Tasks (Optional)

For async evaluation:

python
from wger.trophies.tasks import evaluate_user_trophies_task

# Evaluate asynchronously
evaluate_user_trophies_task.delay(user_id)

Performance Considerations

  • Denormalized Statistics: UserStatistics table provides O(1)
    lookups
  • Incremental Updates: Statistics update incrementally, not full
    recalculation
  • Inactive User Skipping: Users inactive >30 days are skipped
  • Bulk Operations: Batch evaluation supports chunking for large
    user sets

Testing

Run the trophy test suite:

bash
# All trophy tests
python manage.py test wger.trophies.tests

# Specific test files
python manage.py test wger.trophies.tests.test_models
python manage.py test wger.trophies.tests.test_checkers
python manage.py test wger.trophies.tests.test_services
python manage.py test wger.trophies.tests.test_api
python manage.py test wger.trophies.tests.test_integration

Initial Trophies

The system includes 10 initial trophies.

  1. Beginner: Complete your first workout
  2. Unstoppable: Maintain a 30-day workout streak
  3. Weekend Warrior: Work out on Saturday and Sunday for 4 consecutive
    weekends
  4. Lifter: Lift a cumulative total of 5,000 kg
  5. Atlas: Lift a cumulative total of 100,000 kg
  6. Early Bird: Complete a workout before 6:00 AM
  7. Night Owl: Complete a workout after 9:00 PM
  8. New Year, New Me: Work out on January 1st
  9. Phoenix (Hidden): Return to training after being inactive for
    30 days
  10. PR Trophy Achieve a new Personal Record on any exercise

Load them with: python manage.py loaddata initial_trophies

Troubleshooting

Trophies not being awarded

  1. Check if trophy system is enabled: TROPHIES_ENABLED = True
  2. Check user's profile: user.userprofile.trophies_enabled
  3. Check user activity: Not inactive >30 days
  4. Check trophy is active: trophy.is_active = True
  5. Recalculate statistics:
    python manage.py recalculate_statistics --user username

Statistics not updating

  1. Check signals are connected (should happen automatically)
  2. Manually recalculate: python manage.py recalculate_statistics --all
  3. Check for errors in logs

Performance issues

  1. Add database indexes (already included in migrations)
  2. Enable Celery for async evaluation
  3. Adjust TROPHIES_INACTIVE_USER_DAYS to skip more users
  4. Disable trophies for inactive users in bulk

License

AGPL-3.0 (same as wger Workout Manager)


Overview (`extras/docker/base/README.md`)

Development image for wger - Base image

This is the base image for some of the other wger images and offers no
functionality, it's only use is to provide some common dependencies.

If you want to develop, try wger/server.

Contact

Feel free to contact us if you found this useful or if there was something that
didn't behave as you expected. We can't fix what we don't know about, so please
report liberally. If you're not sure if something is a bug or not, feel free to
file a bug anyway.

Sources

All the code and the content is freely available:

Licence

The application is licenced under the Affero GNU General Public License 3 or
later (AGPL 3+).

The initial exercise and ingredient data is licensed additionally under one of
the Creative Commons licenses, see the individual exercises for more details.

The documentation is released under a CC-BY-SA either version 4 of the License,
or (at your option) any later version.

Some images where taken from Wikipedia, see the SOURCES file in their respective
folders for more details.


Overview (`extras/docker/demo/README.md`)

Demo image for wger

wger (ˈvɛɑɐ) Workout Manager is a free, open source web application that help
you manage your personal workouts, weight and diet plans and can also be used
as a simple gym management utility. It offers a REST API as well, for easy
integration with other projects and tools.

Please note that this image will overwrite your data when you pull a new version,
it is only intended as an easy to setup demo. If you want to host your own
instance, take a look at the provided docker compose file. That config will
persist your database and uploaded images:

https://github.com/wger-project/docker

Installation

This docker image contains an instance of the application running as a WSGI
process under apache with a sqlite database. It is useful to just try it out and
play around. To start it:

docker run -ti --name wger.demo --publish 8000:80 wger/demo

Then just open http://localhost:8000 and log in as: admin, password adminadmin

To stop the container:

sudo docker container stop wger.demo

To start developing again:

sudo docker container start --attach wger.demo

Building

If you build this yourself, keep in mind that you must build from the
project root!

docker build -f extras/docker/demo/Dockerfile --tag wger/demo .

Contact

Feel free to contact us if you found this useful or if there was something that
didn't behave as you expected. We can't fix what we don't know about, so please
report liberally. If you're not sure if something is a bug or not, feel free to
file a bug anyway.

Sources

All the code and the content is freely available:

Licence

The application is licenced under the Affero GNU General Public License 3 or
later (AGPL 3+).

The initial exercise and ingredient data is licensed additionally under one of
the Creative Commons licenses, see the individual exercises for more details.

The documentation is released under a CC-BY-SA either version 4 of the License,
or (at your option) any later version.

Some images where taken from Wikipedia, see the SOURCES file in their respective
folders for more details.


Overview (`extras/docker/development/README.md`)

Development image for wger

Please consult https://wger.readthedocs.io/en/latest/development/docker.html for
instructions on how to use this image.


Overview (`extras/docker/production/README.md`)

Production image for wger

wger (ˈvɛɑɐ) Workout Manager is a free, open source web application that help
you manage your personal workouts, weight and diet plans and can also be used
as a simple gym management utility. It offers a REST API as well, for easy
integration with other projects and tools.

Usage

It is recommended to use this image with the provided docker compose, which has all the different
services configured:

https://github.com/wger-project/docker

Contact

Feel free to contact us if you found this useful or if there was something that
didn't behave as you expected. We can't fix what we don't know about, so please
report liberally. If you're not sure if something is a bug or not, feel free to
file a bug anyway.

Sources

All the code and the content is freely available:

Licence

The application is licenced under the Affero GNU General Public License 3 or
later (AGPL 3+).

The initial exercise and ingredient data is licensed additionally under one of
the Creative Commons licenses, see the individual exercises for more details.

The documentation is released under a CC-BY-SA either version 4 of the License,
or (at your option) any later version.

Some images where taken from Wikipedia, see the SOURCES file in their respective
folders for more details.


Overview (`wger/core/static/images/logos/app-store/README.md`)

App Store

https://developer.apple.com/app-store/marketing/guidelines/

App Store ist a trademark of Apple Inc., registered in the U.S. and other countries.


Overview (`wger/core/static/images/logos/play-store/README.md`)

Play Store

https://partnermarketinghub.withgoogle.com/brands/google-play/visual-identity/badge-guidelines/

Google Play and the Google Play logo are trademarks of Google LLC.


--- METRICS ---