Skip to content

Conversation

@felixguendling
Copy link

@felixguendling felixguendling commented Oct 20, 2025

Summary

It would be nice to show brand logos for transit agencies in apps. Many apps already show logos but have to use a side channel because GTFS does not support logos yet. This proposal is based on the way it's modeled in GBFS (except that I propose to make it optional in GTFS). Since it works well there, it should work for GTFS as well.

For Transitous we are planning to add logos for agencies and my idea was to not build yet another side channel to do this (like probably all existing apps) but rather support the ecosystem by proposing a standard way.

Usually, the discussion happens in an issue, but new guidelines state that

if the proposal’s scope is already well-defined, beginning directly at the Pull Request Stage is appropriate.

Since the scope is well-defined, I decided to follow @etienne0101's request.

This is only a first draft. More requirements like transparent background (which is basically the default for SVG, that's why I think this requirement might not be needed here), etc. or an additional URL for 16x16 rasterized images can be added as well (but this could also be done in a separate PR to keep discussion + scope small for this). Just let me know.

Describe the Problem

Currently, apps can't show brand logos for transit agencies based on the GTFS feed and have to work around this via side channels.

Use Cases

Apps showing brand logos to customers

Proposed Solution

Based on how GBFS handles it. Add a new agency_brand_image_url column to agency.txt.

Type of change

GTFS Schedule

  • Functional Change
  • Non-Functional Change
  • Documentation Maintenance

GTFS Realtime

  • Specification Change
  • Specification Change (Experimental Field)

Additional Information

Proposed Discussion Period

Since the issue #76 didn't come to a consensus, discussion should take as long as we don't have consensus.

Testing Details

  • Consumer(s): TBD
  • Producer(s): TBD
  • Estimated Testing Period: TBD

Proposal Update Tracker

Date Update Description
(YYYY-MM-DD) Add agency_brand_image_url to agency

Added optional field for agency brand image URL with requirements as requested by @etienne0101.

This is only a first draft. More requirements like transparent background, size, etc. or an additional URL for 16x16 rasterized images can be added based as well.
Added new fields for brand asset management and updated requirements.
@paulswartz
Copy link
Contributor

Open to thoughts from other consumers here, but isn't this possible already? There's an agency_url and that website likely has <link rel="icon">, <link rel="apple-touch-icon"> or <meta property="og:image"> URLs.

Are there cases you're seeing where the agency website doesn't provide what you need?

@felixguendling
Copy link
Author

felixguendling commented Oct 20, 2025

Nice idea. I haven't thought about this.

I did some quick random tests:

The SNCF apple-touch-icon
grafik

What I would've expected (just in a circle/square shape):
https://www.groupe-sncf.com/images/logo-light.svg

Trenitalia's og:image: https://www.trenitalia.com:443null

Warszawski Transport Publiczny provides only a favicon.ico (the spec would require a SVG):
https://www.wtp.waw.pl

Portland Streetcar has the favicon commented out in their HTML (and also my browser doesn't show any favicon when visiting their website):
https://portlandstreetcar.org/

grafik

So overall this is probably a good fallback solution (with unclear a licensing situation). The solution proposed in this PR would give agencies more control to show a different icon that's specifically designed to be shown to app users. The agency_brand_image_url might be a different icon than the favicon (see SNCF) and should definitely be SVG (which is not always the case for agency websites).

@kona314
Copy link

kona314 commented Oct 20, 2025

Thanks for the PR, this would be a great addition. As you point out, lots of apps are having to invent their own versions of this, so there's clearly need.

I think it's really important to define more requirements for using these fields:

  • Most agencies (if not all) have multiple versions of their logo. Which one should be used?
    • Presumably, whatever is considered "main" or "primary" is the answer. My local transit agency (also my employer, but I'm here speaking for myself) has a very wide, rectangular logo, but the spec requires a square or a circle. Does this mean they should use the secondary, 1:1 aspect ratio variant of the logo? Or squeeze the primary, wide one into a square with a bunch of empty space on the top and bottom?
    • Is it expected that it would usually/always be presented in a small format? This affects the amount of detail visible and what version of the logo would be appropriate. Many agencies have simplified versions for small presentation (e.g. favicons).
    • To this end, is it appropriate to require a square or circle at all?
  • Some brand guidelines impose rules around the background for a logo, so we may see agencies insist on putting a non-transparent background in these images. I'm open to ideas, but I think we should at least state that it's recommended for agencies to publish with a transparent background.
  • How should caching work?
    • I would argue the last modified column can/should be dropped entirely, and we modify the URL column's description to state that consumers should be expected to (1) check this URL at least as frequently as when ingesting a new version of the feed (though some may opt for more often) and (2) rely on standard HTTP headers for caching, just like for the feed itself.
    • I recognize GBFS uses the last modified column, I don't know much about GBFS or why they would have chosen to adopt the approach they did, but this would seem to work well in a GTFS context.
  • I notice GBFS also has a field for a dark mode URL. Should we include something similar?
  • Should there be some mention of what the terms are/are not recommended to include?
    • Presumably, if the agency is including a logo URL, there should be some understanding that developers are allowed to use it for something, but we also don't want consumers assuming they have full rights to the image when the terms may be more nuanced. I might even go so far as to say including a logo URL should imply certain terms, but I recognize this quickly gets messy to define.

Updated the descriptions for agency_brand_image_url and agency_brand_image_url_dark to recommend using a transparent background.
@felixguendling
Copy link
Author

felixguendling commented Oct 20, 2025

Thank you for your quick feedback!

I just forgot to add agency_brand_image_url_dark in my first draft. It's there now.

I might even go so far as to say including a logo URL should imply certain terms, but I recognize this quickly gets messy to define.

I think if we find a wording that 99% of the agencies and app developers would be fine with, that would be very strong. Otherwise, I'd go with your proposal to add a recommendation of what terms should look like. Any ideas what to write there? Otherwise, we could maybe leave it for a later addition as this change won't break anything (it's just a recommendation).

For caching, I just thought that GBFS might've had a reason to design it this way but I'm also completely fine to state that standard HTTP Cache-Control headers apply. Any other opinions on this?

I added a recommendation for the background to be transparent. Maybe you can check again?

To this end, is it appropriate to require a square or circle at all?

I'm open to drop this requirement. From a developer and app designer view it would definitely help to know that width==height (aspect ration = 1). Otherwise, random logo formats can quickly destroy your app design or even make it unusable.

Many agencies have simplified versions for small presentation (e.g. favicons).

This is what I meant with an additional field for 16x16 icons. My idea was to put this into another PR but I am open to add it here if there's a consensus that this is a good idea. Any opinions?

Or squeeze the primary, wide one into a square with a bunch of empty space on the top and bottom?

I think that's an existing problem that most agencies probably have solved in some way. So they probably already have their logo in different formats and can select one that fits.

Updated agency brand fields to include caching headers requirements.
@felixguendling
Copy link
Author

I removed the last modified column and stated that consumers should respect standard HTTP caching headers. I think that makes it clear that files should not be downloaded before max-age expired?

Thank's again for your feedback.

Let me know if there's anything else!

@kona314
Copy link

kona314 commented Oct 21, 2025

I think if we find a wording that 99% of the agencies and app developers would be fine with, that would be very strong. Otherwise, I'd go with your proposal to add a recommendation of what terms should look like. Any ideas what to write there?

This is not perfect, but to start the conversation: "It is recommended that the terms permit feed consumers, without taking additional actions, to use the logo in reference to the agency's services broadly throughout their products, provided an attribution citing these terms is visible to users somewhere in these products."

We might also want guidance on what the lack of terms enables a developer to do. I'm not sure what the right answer is on this.

I'm open to drop this requirement. From a developer and app designer view it would definitely help to know that width==height (aspect ration = 1). Otherwise, random logo formats can quickly destroy your app design or even make it unusable.

Agreed, there are many contexts in my own app I'd use a 1:1 icon, but a variable aspect ratio would be very tricky to get right. However, there are also contexts where this variability is less impactful, and further still there are contexts where this variability is actually useful (such as presenting a "full" or "normal" version of the logo, rather than an alternate optimized for 1:1 use). Transit App uses variable aspect ratios all over the place, for example, I'm sure they'll be weighing in soon enough. Seeing as GBFS went with a 1:1 requirement, it's probably fine to leave it for consistency, but IMO it would be ideal to have it as a separate field since a brand image in and of itself isn't inherently 1:1.

This is what I meant with an additional field for 16x16 icons. My idea was to put this into another PR but I am open to add it here if there's a consensus that this is a good idea. Any opinions?

I would support including this now but don't have a strong opinion. But, I do think we need to include some guidance to feed producers that specifies the agency_brand_image_url should point at an image that is expected to appear at reasonably large sizes and does not need to be simplified for small presentation, and I think that this lends itself nicely to having a small image URL included in this PR to address both use cases at once.

Perhaps, considering both this and the aspect ratio item, the answer is to have e.g. agency_brand_image_url_main, agency_brand_image_url_square, and agency_brand_image_url_16x16. This gets to be a lot with dark alternates of each, but does enable most every logo use case I can think of—without getting fully ridiculous, at least :)

I think that's an existing problem that most agencies probably have solved in some way. So they probably already have their logo in different formats and can select one that fits.

Sure, I just think we should state specifically that the best practice in this case is to use whatever version has been tailored for a 1:1 format. One would hope this is obvious, but I've seen plenty of logo crimes out there, which is why I want to make sure the spec is clear.

I think, taking all of the above together (less the three fields option) and making more consistent use of RFC 2119, I'm thinking of a complete description something along the lines of:

A fully qualified URL pointing to the location of a graphic file representing the agency's brand. The file SHOULD have a transparent background and contain a version of the brand image optimized to fill square or round formats larger than 16x16. Consumers SHOULD respect standard HTTP caching headers when fetching this file. File MUST be in SVG V1.1 format and MUST be either square or round.

An additional question having thought on this some more:

  • Are we expecting users' devices to request the image directly, or to request a version saved on consumers' servers? This is probably also good guidance to include somewhere (for both producers and consumers). I don't see this specified in GBFS.
    • I can see pros and cons to each. It would of course be simpler for clients to request it directly, and for any well-configured server the traffic should be no big deal, but I can see how this might cause some agencies to hesitate.
    • Client apps today don't generate a large amount of (or, often, any) traffic to agency servers, so this would be a departure from that.

Updated the definitions for agency brand URLs in the reference documentation to clarify usage and requirements.
Updated the recommendation for consumers to respect HTTP caching headers when fetching the agency brand terms URL.
@felixguendling
Copy link
Author

felixguendling commented Oct 21, 2025

  • I added the following to both image URLs (default + dark)

    A data consumer MUST store the brand image on their own servers to avoid direct traffic from end user devices to the agencies web servers.

    Regarding which web server serves the icon: I would propose to put the burden on the data consumer. I would like to make it as easy as possible for the producer and eliminate all barriers that could be used as an argument against publishing feeds with logos. Since traffic can always be an argument against adding the logo, the consumer should host the logos. But I am open to other opinions.

  • Thank you very much for your proposal for usage conditions! I took it verbatim. We can change it in case someone has ideas for improvement. Maybe your proposed terms could be states as "this is the default if you don't set agency_brand_terms_url"? Something like the following?

    If agency_brand_terms_url is not set, this permits feed consumers, without taking additional actions, to use the logo in reference to the agency's services broadly throughout their products

  • Regarding extending to

    • agency_brand_image_url_main
    • agency_brand_image_url_square
    • agency_brand_image_url_16x16
    • agency_brand_image_url_dark_main
    • agency_brand_image_url_dark_square
    • agency_brand_image_url_dark_16x16

    I would like to wait for more feedback (e.g. experiences from those who already developed apps with logos) to get a broader view on this topic.

    I think that already the 1:1 SVG with a light+dark version would bring a lot of value to client apps and having six different URLs could become overwhelming for small agencies. But I definitely see value of a 16x16 logo that can be displayed for example on a map.

@skinkie
Copy link
Contributor

skinkie commented Oct 21, 2025

-1

Introduce a branding.txt, have a branding_id, give that all the properties that you propose, refer branding_id from agency.txt, routes.txt, trips.txt

Make it clear what branding is, it is rider facing, signatures, colours, names, etc.

That will make agency.txt a true operator thing again.

@miklcct
Copy link
Contributor

miklcct commented Oct 21, 2025

-1

Introduce a branding.txt, have a branding_id, give that all the properties that you propose, refer branding_id from agency.txt, routes.txt, trips.txt

Make it clear what branding is, it is rider facing, signatures, colours, names, etc.

That will make agency.txt a true operator thing again.

agency.id should not be an operator thing. For example, London Buses are operated by a large number of operators but it is clearly one agency.

@skinkie
Copy link
Contributor

skinkie commented Oct 21, 2025

@miklcct nope, if they are operated by a large number of operators, all these operators could operate their own CAD-AVL system, therefore produce their own GTFS-RT. Passenger facing they might look the same thing, hence they share the same branding_id.

@felixguendling
Copy link
Author

-1

Introduce a branding.txt, have a branding_id, give that all the properties that you propose, refer branding_id from agency.txt, routes.txt, trips.txt

Make it clear what branding is, it is rider facing, signatures, colours, names, etc.

In your comment #76 (comment) you suggested to put it into agency.txt:

It might be but only as part of agency.txt, not feed_info.txt.

That will make agency.txt a true operator thing again.

I would like to point you to the Guiding Principles where it says

There is potentially a large amount of operations-oriented information that transit agencies might want to transmit internally between systems. GTFS is not intended for that purpose and there are potentially other operations-oriented data-standards that may be more appropriate.

Therefore arguing about it being a operator thing is not relevant for GTFS.


However, I see value in being able to use brands for routes as well as different routes could then have their own logos. So I am not opposed to introduce a new file for branding information to not have to duplicate branding information across files.

@skinkie
Copy link
Contributor

skinkie commented Oct 21, 2025

In your comment #76 (comment) you suggested to put it into agency.txt:

I did because you were suggesting a general feed branding, that would never work for multi agency feeds.

Therefore arguing about it being a operator thing is not relevant for GTFS.

The operator thing is not relevant, but given that a single operator is operating with different brands that operator is a single agency with a single system. That artificially must splits it operation over multiple agencies because GTFS does not support branding.

The opposite is also true. I would argue @miklcct just made that case.

@miklcct
Copy link
Contributor

miklcct commented Oct 21, 2025

In your comment #76 (comment) you suggested to put it into agency.txt:

I did because you were suggesting a general feed branding, that would never work for multi agency feeds.

Therefore arguing about it being a operator thing is not relevant for GTFS.

The operator thing is not relevant, but given that a single operator is operating with different brands that operator is a single agency with a single system. That artificially must splits it operation over multiple agencies because GTFS does not support branding.

The opposite is also true. I would argue @miklcct just made that case.

Your point of introducing a new file is valid but can you please don't confuse the matter by mentioning operators?

London Buses have a different brand for its SL and BL prefixed routes compared to ordinary routes, and it is completely irrelevant to which operator runs any of its routes.

@skinkie
Copy link
Contributor

skinkie commented Oct 21, 2025

Your point of introducing a new file is valid but can you please don't confuse the matter by mentioning operators?

The problem is GTFS combining distinct concepts. When we discuss these concepts we must make a distinction. Currently agency.txt is used as a way to differentiate on branding. For example FlixTech is an operator, their GTFS consists of FlixBus and FlixTrain. That is something artificial to facilitate branding on Google Maps.

London Buses have a different brand for its SL and BL prefixed routes compared to ordinary routes, and it is completely irrelevant to which operator runs any of its routes.

Who do you call for lost and found?

Added field definitions for brands.txt and updated agency.txt to include brand_id references.
@felixguendling
Copy link
Author

felixguendling commented Oct 21, 2025

I changed it to

  • a new file brands.txt
  • agency.brand_id references brands.brand_id
  • routes.brand_id references brands.brand_id
  • trips.brand_id references brands.brand_id
  • not yet, but could be (?): do the same for stops.txt (e.g. to reference the brand operating a particular stop?)

More ideas?

@skinkie
Copy link
Contributor

skinkie commented Oct 21, 2025

  • not yet, but could be (?): do the same for stops.txt (e.g. to reference the brand operating a particular stop?)

I think the original reason for the stop_icon proposal was Google Maps doing some localized cartography. For example metro stops commonly have pretty distinguished way finding. So here the optical appearance is more important than meta descriptions.

Updated brand_id field to be required and added new fields for brand_name, brand_url, and brand_phone with their descriptions.
@felixguendling
Copy link
Author

felixguendling commented Oct 21, 2025

I added brand_name, brand_url and brand_phone. Not sure if that's redundant now with agency_* but maybe in some cases it's different.


agency_id is currently described as

Identifies a transit brand which is often synonymous with a transit agency. Note that in some cases, such as when a single agency operates multiple separate services, agencies and brands are distinct. This document uses the term "agency" in place of "brand". A dataset may contain data from multiple agencies.

This is not really fitting anymore if we add brands.txt. Any ideas on how to deal with this?


Edit: Maybe we should state that

  • if a trip does not have a brand_id it will fall back to the route's brand_id
  • if a route does not have a brand_id it will fall back to the agency's brand_id

?

@felixguendling felixguendling changed the title Add agency_brand_image_url to agency Add brands.txt Oct 21, 2025
@miklcct
Copy link
Contributor

miklcct commented Oct 22, 2025

Your point of introducing a new file is valid but can you please don't confuse the matter by mentioning operators?

The problem is GTFS combining distinct concepts. When we discuss these concepts we must make a distinction. Currently agency.txt is used as a way to differentiate on branding. For example FlixTech is an operator, their GTFS consists of FlixBus and FlixTrain. That is something artificial to facilitate branding on Google Maps.

agency.txt is supposed to be the entry point for passenger contacts, not for branding.

In this case, the agency is supposed to be "Flix" as all of FlixBus and FlixTrain have the same passenger-facing portal. They are booked and contacted in the same way.

London Buses have a different brand for its SL and BL prefixed routes compared to ordinary routes, and it is completely irrelevant to which operator runs any of its routes.

Who do you call for lost and found?

TfL

I added brand_name, brand_url and brand_phone. Not sure if that's redundant now with agency_* but maybe in some cases it's different.

Brand name is clearly needed, brand URL as well as there are real-world uses. I am not sure if brand phone has real-world uses at this moment.

agency_id is currently described as

Identifies a transit brand which is often synonymous with a transit agency. Note that in some cases, such as when a single agency operates multiple separate services, agencies and brands are distinct. This document uses the term "agency" in place of "brand". A dataset may contain data from multiple agencies.

This is not really fitting anymore if we add brands.txt. Any ideas on how to deal with this?

I would describe an agency as an entity which serves as the primary contact for a transit system. Depending on the locale, it may be an authority, an operator, a local partnership or something else.

Exactly. And this will hopefully avoid the route_short name abuse.

You mean for example "ICE", "TGV" or "IC" would be the brand?

Highspeed train in Germany:

  • brand=ICE
  • route_short_name=16
  • trip_short_name=1034
  • display as "ICE 1034"

Suburban train in Germany:

  • brand=S-Bahn
  • route_short_name=6
  • trip_short_name=12345
  • display as "S6"

Regional train in Germany:

  • brand=RB
  • route_short_name=75
  • trip_short_name=28723
  • display as "RB 75 (28723)"

(all examples are real-world examples we needed to fix in order to be displayed similar to the official apps, i.e. in Germany "DB Navigator")

The only missing information then is how to build the display name. For Transitous we had a long discussion at public-transport/transitous#1015 and then needed to solve it with some scripts that are applied while loading data (because GTFS doesn't provide this information yet): https://github.com/public-transport/transitous/blob/main/scripts/de-DELFI.lua

Maybe brand information could improve this?

No. The route short name should still be something like S6 or RB75 since these are the string which is shown on the train itself. The RB75 will have the brand "RegioBahn", the S6 will have the brand "S-Bahn", etc.

I interpret the brand name would be for use in, for example, the "Superloop" routes in London, so the SL1 route will have brand=Superloop and route_short_name=SL1. When this route is encountered in client apps, the Superloop brand is applied to it but the route_short_name is still displayed verbatim.

@felixguendling
Copy link
Author

No. The route short name should still be something like S6

Only showing route name does not work for the other examples I made (which you seem to have missed):

  • "RB 75 (28723)" (route name + trip name relevant)
  • "ICE 1034" (only trip name shown to customers, route name / line exists but is not commonly used in customer information such as tickets, departure boards or official booking apps).

Therefore, the "only showing route_short_name" approach is not sufficient for the examples you didn't mention. Even if you also show the trip name somewhere in the details it's just plain wrong for the "ICE 1034" example to show it's line number instead of the train number.

We introduced a display_name property on trip level and scripting in MOTIS to overwrite this field. So we have something that works most of the time and matches what customers will find on real-world departure boards quite often. However, this is not possible with vanilla GTFS at the moment.

@miklcct
Copy link
Contributor

miklcct commented Oct 22, 2025

No. The route short name should still be something like S6

Only showing route name does not work for the other examples I made (which you seem to have missed):

  • "RB 75 (28723)" (route name + trip name relevant)
  • "ICE 1034" (only trip name shown to customers, route name / line exists but is not commonly used in customer information such as tickets, departure boards or official booking apps).

Therefore, the "only showing route_short_name" approach is not sufficient for the examples you didn't mention. Even if you also show the trip name somewhere in the details it's just plain wrong for the "ICE 1034" example to show it's line number instead of the train number.

We introduced a display_name property on trip level and scripting in MOTIS to overwrite this field. So we have something that works most of the time and matches what customers will find on real-world departure boards quite often. However, this is not possible with vanilla GTFS at the moment.

If it is not in customer information it should not be part of the GTFS. GTFS is only for customer information. If the board shows ICE 1034 then ICE 1034 should be the route_short_name.

@jspetrak
Copy link

@miklcct "ICE 1034" is trip name, not a route name. Most of trains do not have any route but it is not supported by GTFS. It requires every trip as part of (named) route. So you get many artifical routes from rail
feed providers and it just makes mess in data or UI.

@miklcct
Copy link
Contributor

miklcct commented Oct 22, 2025

What do you mean by a trip not having a route (line in Transmodel)? How do you convey to your passengers the equivalent of "Take line A towards Eatonville" for your services? How do your passengers identify other trips which run to the same places?

@felixguendling
Copy link
Author

I'm sorry, I led the discussion a bit off topic with my examples. Maybe we should have that discussion in another, separate issue. I think there are different ways to solve this and it's only partly a GTFS problem since the data quality is also not always good.

On topic: I would really like to hear from those who already went through adding branding information such as logos to their apps like @gcamp and @bdferris-v2: how we can further improve this proposal? Is there anything missing? Should we change/add/reformulate it? Do you see value in adding this information to GTFS?

@jspetrak
Copy link

What do you mean by a trip not having a route (line in Transmodel)? How do you convey to your passengers the equivalent of "Take line A towards Eatonville" for your services? How do your passengers identify other trips which run to the same places?

By default, train has number, first and last stop, and that's it. You may have trains in numbered sequence running in certain interval between the same O/D but they can be not assigned any line. So you announce "train 123 to XYZ". That's how rail was working for last 150+ years. Lines were added in last decades and aren't common in every country.

@miklcct
Copy link
Contributor

miklcct commented Oct 22, 2025

What do you mean by a trip not having a route (line in Transmodel)? How do you convey to your passengers the equivalent of "Take line A towards Eatonville" for your services? How do your passengers identify other trips which run to the same places?

By default, train has number, first and last stop, and that's it. You may have trains in numbered sequence running in certain interval between the same O/D but they can be not assigned any line. So you announce "train 123 to XYZ". That's how rail was working for last 150+ years. Lines were added in last decades and aren't common in every country.

In this case the 123 is the route number. The same as announcing "bus 52 to Willesden", where 52 is a route number.

@skinkie
Copy link
Contributor

skinkie commented Oct 22, 2025

In this case the 123 is the route number. The same as announcing "bus 52 to Willesden", where 52 is a route number.

And in The Netherlands we don't have routes (lines) at all for trains. So it is only IC Amsterdam.

@miklcct
Copy link
Contributor

miklcct commented Oct 22, 2025

In this case the 123 is the route number. The same as announcing "bus 52 to Willesden", where 52 is a route number.

And in The Netherlands we don't have routes (lines) at all for trains. So it is only IC Amsterdam.

In GB the information is shown in form as, for example, "a Mildmay line service", on the departure boards and announcements, where "Mildmay line" is the route name.

However, the line name can be as generic as the whole operator called the same line, such as "South Western Railway".

@gcamp
Copy link
Contributor

gcamp commented Oct 22, 2025

I'm not sure there's much to learn from the previous iteration of the same ideas, but I'm still putting it here GTFS-ModesAndNetworks. It was generally based on what we were doing at Transit.

I think what is proposed here makes sense to me except for the size ratio of the images, I don't think we can enforce a square or circle image. I understand this makes implementation way easier, but a lot of logos are actually logo type and would be simply illegible in a boxed-in format.

At Transit we have 3 variants of images : light mode and dark mode as proposed here but also mono (no colour). Depending on the context it might be useful. We use it internally for route images however and not brand images.

@felixguendling
Copy link
Author

felixguendling commented Oct 22, 2025

@gcamp thank you for your feedback!

@kona314 proposed this:

Perhaps, considering both this and the aspect ratio item, the answer is to have e.g. agency_brand_image_url_main, agency_brand_image_url_square, and agency_brand_image_url_16x16. This gets to be a lot with dark alternates of each, but does enable most every logo use case I can think of—without getting fully ridiculous, at least :)

Do you think that would help? Should we add a mono URL?

Then it would be:

  • brand_image_url_mono [EDIT: this is probably also SVG?]
  • brand_image_url_main
  • brand_image_url_square
  • brand_image_url_16x16
  • brand_image_url_main_dark
  • brand_image_url_square_dark
  • brand_image_url_16x16_dark

@kona314
Copy link

kona314 commented Oct 22, 2025

I'm thinking we should refactor this a bit (again).

The brand vs. agency distinction is a worthwhile discussion for another context. I believe the intent of this PR is simply to be able to show images and iconography that riders are familiar with in contexts that appropriate--an agency icon, a route symbol, etc..

To this end, I'm wondering if we should simplify this down to an image_assets.txt file. In agency.txt, routes.txt, etc. we could have a icon_image_id (and/or logo_image_id, icon_16x16_image_id, etc.) referencing IDs in this file. Columns could require that they reference a square image or not, but this would be constrained or specified on the column, not the asset.

The base of the file would look something like the below. Each row represents an asset and variants of each are in the columns. I didn't add a mono column but we could throw that in too, though we'd probably have to rework the presence fields to require at least one of image_url or image_url_mono. We could also add an aspect ratio column but I'm not sure this is valuable, consumers can calculate that on import. A future reworking of brands and agencies could reference images in this file as appropriate.

image_assets.txt

File: Conditionally Required

Primary key (image_id)

Field Name Type Presence Description
image_id Unique ID Required Identifies an image referenced in the feed.
image_terms_url URL Optional A fully qualified URL pointing to the location of a page that defines the license terms of the image.

It is recommended that the terms permit feed consumers, without taking additional actions, to use the image in reference to services contained in the feed broadly throughout their products, provided an attribution citing these terms is visible to users somewhere in these products.

Consumers SHOULD respect standard HTTP caching headers when fetching this file.
image_url URL Required A fully qualified URL pointing to the location of a graphic file. The file MUST be in SVG v1.1 format and SHOULD have a transparent background. Consumers SHOULD respect standard HTTP caching headers when fetching this file.

A data consumer MUST store the brand image on their own servers to avoid direct traffic from end user devices to the agencies' web servers.
image_url_dark URL Optional A fully qualified URL pointing to the location of a graphic file, for use in dark mode applications. The file MUST be the same size as the one in image_url and represent an otherwise identical image, except for any dark mode optimizations. When this value is specified and a consuming application is in dark mode, the application SHOULD use this variant of the image, otherwise they should use the standard image. The file MUST be in SVG v1.1 format and SHOULD have a transparent background. Consumers SHOULD respect standard HTTP caching headers when fetching this file.

A data consumer MUST store the brand image on their own servers to avoid direct traffic from end user devices to the agencies' web servers.

@gcamp
Copy link
Contributor

gcamp commented Oct 23, 2025

I think having a dedicated images file is a good idea, because images aren't limited to agency/brands, they can also apply to routes, stops, vehicles, etc.

@johnhelmuth-st
Copy link

I think this PR should focus on the images, and leave the brand specific metadata to a different issue/PR.

If a separate branding file is required to split the agency contact / URL information into a brand specific metadata, that file can include a foreign key for brand specific images if that use case needs to be addressed.

+1 to a dedicated image file.

@johnhelmuth-st
Copy link

@gcamp said

I think what is proposed here makes sense to me except for the size ratio of the images, I don't think we can enforce a square or circle image. I understand this makes implementation way easier, but a lot of logos are actually logo type and would be simply illegible in a boxed-in format.

Our agency recently settled on a new naming and signage standard for light rail stations that would be difficult to reproduce in a square logo, and possibly confusing in a text-only format. Having a URL for this icon as an SVG would help our passengers to identify the stations on a map.

Offered as a use-case for a single agency.

@felixguendling
Copy link
Author

How would you reference those images? Directly from the agency or via a brand?
If directly via the agency, adding a brand later will introduce redundancy?

@kona314
Copy link

kona314 commented Oct 23, 2025

Yes, agencies.txt would have e.g. logo_image_id and logo_16x16_image_id referencing image_ids defined in image_assets.txt.

If a future iteration of GTFS includes a separate notion of brand vs. agency, it should include these fields as well, and would be deconflicted the same way as agency_name and agency_url would be with presumptive brand_name and brand_url fields.

@felixguendling felixguendling changed the title Add brands.txt Add images.txt + agency logo Oct 24, 2025
@felixguendling
Copy link
Author

felixguendling commented Oct 24, 2025

Ok, then let's split this from brands.txt discussion and only focus on bringing logos into end user apps. I think you're right that brands.txt can be handled as a orthogonal topic and we don't "destroy" something now that can't be fixed later (at least from what I see now).

I changed it to:

  • images.txt instead of image_assets.txt is maybe sufficient? Also makes it consistent with key names image_id instead of image_asset_id.
  • added alternative text

Questions:

  • If this is a general image database used throughout the feed, should we drop the SVG requirement there and add it to every place where it should be a logo (agency/brand/product logo). Maybe at one point we want to add photos of stops so users can easily identify them or something else where raster images are a better fit?
  • Should we add a image_16x16_url and image_monochrome_url to the image table or is this something for logo_16x16_image_id and logo_monochrome_image_id in the agency table?

Edit: I was thinking to maybe even remove the terms completely. For consumers of large amounts of feeds it's a lot of effort to read all those legalese to check if you can really use it in your app. Maybe we should just enforce @kona314's fall-back terms. What is a logo worth in GTFS if those minimum conditions (i.e. I am allowed to used the logo in my app in reference to their services given I credit the source) are not met?! If a organization (brand/agency/feed producer/etc.) doesn't want their logos in any app they should just not reference it in a GTFS feed. I would like that a consumer can expect to be able to use any reference image (within reasonable default terms). Maybe we need even stricter default terms for this but having to check basically every feed update for every feed for new terms (or even without a feed update - just change the content behind the terms URL) is not feasible.

@kona314
Copy link

kona314 commented Oct 24, 2025

On raster images
I'm torn on this one. I see the value in this flexibility, but I worry about the complexity of mixing very different kinds of images/the likelihood of things getting mixed up. I also think the needs of brand imagery are very different from those of raster images like stop photos, like with the use of different variants (dark, mono) of the "same" image—perhaps a different filename is in order to distinguish the two. iconography.txt? This was my thinking behind the use of "assets" since it's commonly used in design, but I know that's not the most recognizable.

On additional variants
I view each column as a different variant of what is otherwise recognizably the same image. To this end, I feel that image_monochrome_url is appropriate in the image file, but specific sizes or aspect ratios should be a separate image referenced with separate columns in the specific object file (e.g. logo_16x16_image_id in agency.txt). All variants should always be the same, as specified in image_dark_url. This would also allow full buildout of light, dark, and mono variants of both the full size and smaller images.

On terms
I hear where you're coming from on this, and as a developer, I would very much appreciate that simplicity. To your point, it also wouldn't make sense to populate the field but not enable use. However, I think this would block a lot of agencies from utilizing this functionality. Many agencies already have specific needs or requirements for licensing their registered trademarks, and it's important to have the flexibility in the spec for them to express that, otherwise they may not bother at all.

There might be a middle ground with the use of a required image_terms enum column. One value would specify that custom terms in the URL field apply, indicating developers must take action before enabling the image to appear in their apps. Other values would apply pre-defined terms developers can account for in advance. My instinct is that we should leverage Creative Commons licenses and strongly recommend BY-ND, but I fear CC would spook some agencies with registered trademarks and they'd leverage their own terms, so perhaps a basic "GTFS terms" they can opt into would be a worthwhile enum value as well. We would need to make sure any changes to the terms get their own enum value so terms don't change without consent of the publisher.

Other
I noticed you also retained image_url as optional and image_dark_url as conditionally forbidden—this would make it valid to produce a row with an ID and alt text, but no actual image. My proposal above has these are required and optional respectively. If we're adding mono into the mix, it might be best to just require that one of the three variants be populated, so it's not legal to produce an image with no images.

@felixguendling
Copy link
Author

One value would specify that custom terms in the URL field apply, indicating developers must take action before enabling the image to appear in their apps

To be honest, I don't see value of having this in GTFS if then I still need to go through a manual negotiation / signing process. Then it still requires an external process to know which logos I can use and I need to have a manual book keeping. I still need another book keeping for contracts - storing the logo URLs somewhere is the least problem in this process. I can do this already now (without this extension), if I wanted, and this extension would not really help.

GTFS as a standard is only valuable if also the licenses are standardised. I like the enum idea and using standard licenses like the CC family of licenses (or anything else we can come up with as additional options). Licensing the image to be used in conjunction with an agencies' services (without the licensee gaining any other rights) should be the bare minimum. If an external step to request a license is needed anyway, this side channel can also be used to exchange the logo URLs.

I would hope that most agencies want their logos in apps, at least once all their competitors show up with a logo. It's a way to promote a company - basically free marketing. If their lawyers want to give developers a hard time by requiring extra terms, they can already do this without the help of GTFS.

I see the value in this flexibility, but I worry about the complexity of mixing very different kinds of images

In the end it's just a file you download and integrate show in your app. For instance in HTML you can just use <img src="..." alt="..." /> and it'll just work with SVG, PNG, JPEG, etc. I'm not really worried about complexity here. At least for me, adding two files (one for icons, one for raster images) would introduce more complexity than just having one for all images and adding restrictions on data types in the places that reference the image_id.

I noticed you also retained image_url as optional and image_dark_url as conditionally forbidden

I tried to copy from your post by using quote-reply but it removed the table formatting, so I had to manually copy. Seems like I missed this. You're right. Of course we want at least one URL to be set.

Updated image fields to clarify requirements and add new fields.
@kona314
Copy link

kona314 commented Oct 26, 2025

I agree with everything you've said on licensing. My feeling, though, is we need to be cognizant of the realities of how agencies will approach this. As far as I'm aware, agencies in the US typically require some kind of agreement to terms to use their logos (though something written may not always be required?). The MBTA developer license agreement, which covers their GTFS and GTFS-realtime feeds, explicitly does not permit the use of the logo in section 4.1. The NY MTA requires applying for a license.

I think the tension here is fundamentally one between the ideal state and current reality. If the spec requires granting certain use privileges under terms written into the spec, are agencies really going to license their logo with these terms? Or will they simply ignore this and maintain the current status quo? My feeling is the latter, but I would love to be wrong about this.

I'd be interested in hearing from @gcamp or others at Transit what their experience has been on this with agencies around the world. Managing permissions will likely (IMO) be a reality of using a logo for consumers, just as it is today for those that support it, and as a consumer, I don't see tracking approval statuses as an unreasonable burden. What we can do, and the benefit this file would offer, is give agencies the option to make it easier for us by opting in to permissive use right in this file with the image_terms enum I describe above. When custom terms are used, consumers still get the benefit of the image being associated with objects directly in the feed (be it agency logo, route/stop icons, etc.), all we have to do is get terms taken care of and check a box in our backend. To this end, it might be good to specify the image_id should be consistent through feed versions.

Another option might be additional fields indicating whether the terms permit specific presentations within an app while maintaining an agency's custom terms. It would still be incumbent on the developer to understand and accept the full terms, but if the terms say "you may use the logo in [specific context X] as long as there's a link to these terms somewhere," that could be flagged to improve headless operation. However, this might kind of defeat the purpose of either option.

At least for me, adding two files (one for icons, one for raster images) would introduce more complexity than just having one for all images and adding restrictions on data types in the places that reference the image_id.

Sure, if any consumer cares about filetype, they can easily discern this. I guess complexity was the wrong word, it's more that it muddies the waters. Logos and photographs have different needs—it'd be weird to have columns for dark and mono versions of a bus stop photo. Do we want that to be allowed? If not, how would we prevent that in the spec? If so, what's the guidance for producers here? There are photo attributes, like the date it was taken, that we might want but don't apply to brand images, how would we handle that? I think there's value in keeping this narrowed to brand assets/images that communicate visual identity. DAM systems usually treat logos and icons differently from photos for this reason.

Thinking on it more, I think the word "glyphs" captures what I'm thinking about here, so the file would be glyphs.txt with glyph_id etc..

@johnhelmuth-st
Copy link

Does it make sense to re-use attributions.txt instead of adding just a terms URL here? (This could be a dumb idea, but it seems to me that there is some overlap here.)

Also, I dug up what our agency's terms are for the logos we would be putting into our feed. I'm not sure if that would help in this conversation, but I'll throw this out there anyways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Change type: Functional Refers to modifications that significantly affect specification functionalities. GTFS Schedule Issues and Pull Requests that focus on GTFS Schedule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants