diff --git a/prdoc/pr_7671.prdoc b/prdoc/pr_7671.prdoc
new file mode 100644
index 0000000000000000000000000000000000000000..09a1aef40bb09e145b1b98c389f20024d37e0de3
--- /dev/null
+++ b/prdoc/pr_7671.prdoc
@@ -0,0 +1,24 @@
+title: 'Fix: [Referenda Tracks] Resolve representation issues that are breaking PJS apps'
+
+doc:
+- audience: Runtime Dev
+  description: |-
+    The PR #2072 introduces a change in the representation of the `name` field, from a `&str` to a `[u8; N]` array. This is because 
+    tracks can be retrieves from storage, and thus, a static string representation doesn't meet with the storage traits requirements.
+
+    This PR encapsulates this array into a `StringLike` structure that allows representing the value as a `str` for SCALE and metadata
+    purposes. This is to avoid breaking changes.
+
+    This PR also reverts the representation of the `Tracks` constant as a tuple of `(TrackId, TrackInfo)` to accomplish the same
+    purpose of avoid breaking changes to runtime users and clients.
+crates:
+- name: pallet-referenda
+  bump: minor
+- name: collectives-westend-runtime
+  bump: minor
+- name: kitchensink-runtime
+  bump: minor
+- name: rococo-runtime
+  bump: minor
+- name: westend-runtime
+  bump: minor
diff --git a/substrate/frame/referenda/src/lib.rs b/substrate/frame/referenda/src/lib.rs
index b58baa341cf596ef531b6dc4969904236dc791bb..6d67dc5eee0569c8a8c41ea99cd094623c25d752 100644
--- a/substrate/frame/referenda/src/lib.rs
+++ b/substrate/frame/referenda/src/lib.rs
@@ -97,10 +97,11 @@ use self::branch::{BeginDecidingBranch, OneFewerDecidingBranch, ServiceBranch};
 pub use self::{
 	pallet::*,
 	types::{
-		BalanceOf, BlockNumberFor, BoundedCallOf, CallOf, Curve, DecidingStatus, DecidingStatusOf,
-		Deposit, InsertSorted, NegativeImbalanceOf, PalletsOriginOf, ReferendumIndex,
-		ReferendumInfo, ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf, ScheduleAddressOf,
-		TallyOf, Track, TrackIdOf, TrackInfo, TrackInfoOf, TracksInfo, VotesOf,
+		BalanceOf, BlockNumberFor, BoundedCallOf, CallOf, ConstTrackInfo, Curve, DecidingStatus,
+		DecidingStatusOf, Deposit, InsertSorted, NegativeImbalanceOf, PalletsOriginOf,
+		ReferendumIndex, ReferendumInfo, ReferendumInfoOf, ReferendumStatus, ReferendumStatusOf,
+		ScheduleAddressOf, StringLike, TallyOf, Track, TrackIdOf, TrackInfo, TrackInfoOf,
+		TracksInfo, VotesOf,
 	},
 	weights::WeightInfo,
 };
@@ -224,9 +225,31 @@ pub mod pallet {
 
 	#[pallet::extra_constants]
 	impl<T: Config<I>, I: 'static> Pallet<T, I> {
+		/// A list of tracks.
+		///
+		/// Note: if the tracks are dynamic, the value in the static metadata might be inaccurate.
 		#[pallet::constant_name(Tracks)]
-		fn tracks() -> Vec<Track<TrackIdOf<T, I>, BalanceOf<T, I>, BlockNumberFor<T, I>>> {
-			T::Tracks::tracks().map(|t| t.into_owned()).collect()
+		fn tracks() -> Vec<(TrackIdOf<T, I>, ConstTrackInfo<BalanceOf<T, I>, BlockNumberFor<T, I>>)>
+		{
+			T::Tracks::tracks()
+				.map(|t| t.into_owned())
+				.map(|Track { id, info }| {
+					(
+						id,
+						ConstTrackInfo {
+							name: StringLike(info.name),
+							max_deciding: info.max_deciding,
+							decision_deposit: info.decision_deposit,
+							prepare_period: info.prepare_period,
+							decision_period: info.decision_period,
+							confirm_period: info.confirm_period,
+							min_enactment_period: info.min_enactment_period,
+							min_approval: info.min_approval,
+							min_support: info.min_support,
+						},
+					)
+				})
+				.collect()
 		}
 	}
 
diff --git a/substrate/frame/referenda/src/types.rs b/substrate/frame/referenda/src/types.rs
index 861b4605271f6fd0d574fdb3d2618ddd09418c00..c810af341b1e8ad842fa9d21085ed27804a3056f 100644
--- a/substrate/frame/referenda/src/types.rs
+++ b/substrate/frame/referenda/src/types.rs
@@ -19,13 +19,13 @@
 
 use super::*;
 use alloc::borrow::Cow;
-use codec::{Decode, DecodeWithMemTracking, Encode, EncodeLike, MaxEncodedLen};
+use codec::{Compact, Decode, DecodeWithMemTracking, Encode, EncodeLike, Input, MaxEncodedLen};
 use core::fmt::Debug;
 use frame_support::{
 	traits::{schedule::v3::Anon, Bounded},
 	Parameter,
 };
-use scale_info::TypeInfo;
+use scale_info::{Type, TypeInfo};
 use sp_arithmetic::{Rounding::*, SignedRounding::*};
 use sp_runtime::{FixedI64, PerThing, RuntimeDebug};
 
@@ -118,13 +118,61 @@ pub struct Deposit<AccountId, Balance> {
 
 pub const DEFAULT_MAX_TRACK_NAME_LEN: usize = 25;
 
+/// Helper structure to treat a `[u8; N]` array as a string.
+///
+/// This is a temporary fix (see [#7671](https://github.com/paritytech/polkadot-sdk/pull/7671)) in
+/// order to stop `polkadot.js` apps to fail when trying to decode the `name` field in `TrackInfo`.
+#[derive(Clone, Eq, DecodeWithMemTracking, PartialEq, Debug)]
+pub struct StringLike<const N: usize>(pub [u8; N]);
+
+impl<const N: usize> TypeInfo for StringLike<N> {
+	type Identity = <&'static str as TypeInfo>::Identity;
+
+	fn type_info() -> Type {
+		<&str as TypeInfo>::type_info()
+	}
+}
+
+impl<const N: usize> MaxEncodedLen for StringLike<N> {
+	fn max_encoded_len() -> usize {
+		<Compact<u32> as MaxEncodedLen>::max_encoded_len().saturating_add(N)
+	}
+}
+
+impl<const N: usize> Encode for StringLike<N> {
+	fn encode(&self) -> Vec<u8> {
+		use codec::Compact;
+		(Compact(N as u32), self.0).encode()
+	}
+}
+
+impl<const N: usize> Decode for StringLike<N> {
+	fn decode<I: Input>(input: &mut I) -> Result<Self, codec::Error> {
+		let Compact(size): Compact<u32> = Decode::decode(input)?;
+		if size != N as u32 {
+			return Err("Invalid size".into());
+		}
+
+		let bytes: [u8; N] = Decode::decode(input)?;
+		Ok(Self(bytes))
+	}
+}
+
+/// Detailed information about the configuration of a referenda track. Used for internal storage.
+pub type TrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> =
+	TrackDetails<Balance, Moment, [u8; N]>;
+
+/// Detailed information about the configuration of a referenda track. Used for const querying.
+pub type ConstTrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> =
+	TrackDetails<Balance, Moment, StringLike<N>>;
+
 /// Detailed information about the configuration of a referenda track
 #[derive(
 	Clone, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, Eq, PartialEq, Debug,
 )]
-pub struct TrackInfo<Balance, Moment, const N: usize = DEFAULT_MAX_TRACK_NAME_LEN> {
+pub struct TrackDetails<Balance, Moment, Name> {
 	/// Name of this track.
-	pub name: [u8; N],
+	pub name: Name,
 	/// A limit for the number of referenda on this track that can be being decided at once.
 	/// For Root origin this should generally be just one.
 	pub max_deciding: u32,
@@ -795,4 +843,20 @@ mod tests {
 			Err("The tracks that were returned by `tracks` were not sorted by `Id`")
 		);
 	}
+
+	#[test]
+	fn encoding_and_decoding_of_string_like_structure_works() {
+		let string_like = StringLike::<13>(*b"hello, world!");
+		let encoded: Vec<u8> = string_like.encode();
+
+		let decoded_as_vec: Vec<u8> =
+			Decode::decode(&mut &encoded.clone()[..]).expect("decoding as Vec<u8> should work");
+		assert_eq!(decoded_as_vec.len(), 13);
+		let decoded_as_str: alloc::string::String =
+			Decode::decode(&mut &encoded.clone()[..]).expect("decoding as str should work");
+		assert_eq!(decoded_as_str.len(), 13);
+		let decoded_as_string_like: StringLike<13> =
+			Decode::decode(&mut &encoded.clone()[..]).expect("decoding as StringLike should work");
+		assert_eq!(decoded_as_string_like.0.len(), 13);
+	}
 }